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) && (NULL == delete_op) && (NULL == set_op) &&
149 (NULL == set_subsystem) && (!list) && (!monitor))
151 if (TIMEOUT_STATUS_CODE == global_ret)
153 GNUNET_SCHEDULER_shutdown();
159 * Deletion operation finished.
161 * @param cls pointer to operation handle
162 * @param emsg NULL on success, otherwise an error message
165 delete_finished(void *cls, const char *emsg)
167 struct GNUNET_IDENTITY_Operation **op = cls;
171 fprintf(stderr, "%s\n", gettext(emsg));
177 * Creation operation finished.
179 * @param cls pointer to operation handle
180 * @param pk private key of the ego, or NULL on error
181 * @param emsg error message, NULL on success
184 create_finished(void *cls,
185 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk,
188 struct GNUNET_IDENTITY_Operation **op = cls;
193 fprintf(stderr, _("Failed to create ego: %s\n"), emsg);
198 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
201 GNUNET_CRYPTO_ecdsa_key_get_public(pk, &pub);
202 pubs = GNUNET_CRYPTO_ecdsa_public_key_to_string(&pub);
207 privs = GNUNET_CRYPTO_ecdsa_private_key_to_string(pk);
208 fprintf(stdout, "%s - %s\n", pubs, privs);
213 fprintf(stdout, "%s\n", pubs);
222 * Function called by #GNUNET_IDENTITY_set up on completion.
225 * @param emsg error message (NULL on success)
228 set_done(void *cls, const char *emsg)
233 fprintf(stderr, _("Failed to set default ego: %s\n"), emsg);
241 * If listing is enabled, prints information about the egos.
243 * This function is initially called for all egos and then again
244 * whenever a ego's identifier changes or if it is deleted. At the
245 * end of the initial pass over all egos, the function is once called
246 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
247 * be invoked in the future or that there was an error.
249 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
250 * this function is only called ONCE, and 'NULL' being passed in
251 * 'ego' does indicate an error (i.e. name is taken or no default
252 * value is known). If 'ego' is non-NULL and if '*ctx'
253 * is set in those callbacks, the value WILL be passed to a subsequent
254 * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
255 * that one was not NULL).
257 * When an identity is renamed, this function is called with the
258 * (known) ego but the NEW identifier.
260 * When an identity is deleted, this function is called with the
261 * (known) ego and "NULL" for the 'identifier'. In this case,
262 * the 'ego' is henceforth invalid (and the 'ctx' should also be
266 * @param ego ego handle
267 * @param ctx context for application to store data for this ego
268 * (during the lifetime of this process, initially NULL)
269 * @param identifier identifier assigned by the user for this ego,
270 * NULL if the user just deleted the ego and it
271 * must thus no longer be used
275 struct GNUNET_IDENTITY_Ego *ego,
277 const char *identifier)
279 struct GNUNET_CRYPTO_EcdsaPublicKey pk;
283 if ((NULL != set_ego) && (NULL != set_subsystem) && (NULL != ego) &&
284 (NULL != identifier) && (0 == strcmp(identifier, set_ego)))
286 set_op = GNUNET_IDENTITY_set(sh, set_subsystem, ego, &set_done, NULL);
287 GNUNET_free(set_subsystem);
288 set_subsystem = NULL;
289 GNUNET_free(set_ego);
292 if ((NULL == ego) && (NULL != set_ego) && (NULL != set_subsystem))
295 "Could not set ego to `%s' for subsystem `%s', ego not known\n",
298 GNUNET_free(set_subsystem);
299 set_subsystem = NULL;
300 GNUNET_free(set_ego);
303 if ((NULL == ego) && (!monitor))
309 if (!(list | monitor))
311 if ((NULL == ego) || (NULL == identifier))
313 if ((NULL != set_ego) && (0 != strcmp(identifier, set_ego)))
315 GNUNET_IDENTITY_ego_get_public_key(ego, &pk);
316 s = GNUNET_CRYPTO_ecdsa_public_key_to_string(&pk);
317 privs = GNUNET_CRYPTO_ecdsa_private_key_to_string(
318 GNUNET_IDENTITY_ego_get_private_key(ego));
319 if ((monitor) || (NULL != identifier))
324 fprintf(stdout, "%s - %s\n", s, privs);
326 fprintf(stdout, "%s\n", s);
331 fprintf(stdout, "%s - %s - %s\n", identifier, s, privs);
333 fprintf(stdout, "%s - %s\n", identifier, s);
342 * Main function that will be run by the scheduler.
345 * @param args remaining command-line arguments
346 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
347 * @param cfg configuration
353 const struct GNUNET_CONFIGURATION_Handle *cfg)
355 if ((NULL != set_subsystem) && (NULL == set_ego))
357 fprintf(stderr, "Option -s requires option -e to be specified as well.\n");
360 sh = GNUNET_IDENTITY_connect(cfg,
361 (monitor | list) || (NULL != set_ego) ||
362 (NULL != set_subsystem)
366 if (NULL != delete_ego)
368 GNUNET_IDENTITY_delete(sh, delete_ego, &delete_finished, &delete_op);
369 if (NULL != create_ego)
371 GNUNET_IDENTITY_create(sh, create_ego, &create_finished, &create_op);
372 GNUNET_SCHEDULER_add_shutdown(&shutdown_task, NULL);
380 * @param argc number of arguments from the command line
381 * @param argv command line arguments
382 * @return 0 ok, 1 on error
385 main(int argc, char *const *argv)
387 struct GNUNET_GETOPT_CommandLineOption options[] =
388 { GNUNET_GETOPT_option_string('C',
391 gettext_noop("create ego NAME"),
393 GNUNET_GETOPT_option_string('D',
396 gettext_noop("delete ego NAME "),
398 GNUNET_GETOPT_option_flag('d',
400 gettext_noop("display all egos"),
402 GNUNET_GETOPT_option_flag('q',
404 gettext_noop("reduce output"),
406 GNUNET_GETOPT_option_string(
411 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -s) or restrict results to NAME (use together with -d)"),
413 GNUNET_GETOPT_option_flag('m',
415 gettext_noop("run in monitor mode egos"),
417 GNUNET_GETOPT_option_flag('p',
419 gettext_noop("display private keys as well"),
421 GNUNET_GETOPT_option_string(
426 "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)"),
428 GNUNET_GETOPT_option_verbose(&verbose),
429 GNUNET_GETOPT_OPTION_END };
432 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args(argc, argv, &argc, &argv))
434 global_ret = TIMEOUT_STATUS_CODE; /* timeout */
435 res = GNUNET_PROGRAM_run(argc,
438 gettext_noop("Maintain egos"),
442 GNUNET_free((void *)argv);
444 if (GNUNET_OK != res)
449 /* end of gnunet-identity.c */