Merge remote-tracking branch 'origin/master' into credentials
[oweals/gnunet.git] / src / identity / gnunet-identity.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2013 GNUnet e.V.
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
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  * Handle to IDENTITY service.
34  */
35 static struct GNUNET_IDENTITY_Handle *sh;
36
37 /**
38  * Was "list" specified?
39  */
40 static int list;
41
42 /**
43  * Was "monitor" specified?
44  */
45 static int monitor;
46
47 /**
48  * -C option
49  */
50 static char *create_ego;
51
52 /**
53  * -D option
54  */
55 static char *delete_ego;
56
57 /**
58  * -s option.
59  */
60 static char *set_ego;
61
62 /**
63  * -S option.
64  */
65 static char *set_subsystem;
66
67 /**
68  * Operation handle for set operation.
69  */
70 static struct GNUNET_IDENTITY_Operation *set_op;
71
72 /**
73  * Handle for create operation.
74  */
75 static struct GNUNET_IDENTITY_Operation *create_op;
76
77 /**
78  * Handle for delete operation.
79  */
80 static struct GNUNET_IDENTITY_Operation *delete_op;
81
82
83 /**
84  * Task run on shutdown.
85  *
86  * @param cls NULL
87  */
88 static void
89 shutdown_task (void *cls)
90 {
91   if (NULL != set_op)
92   {
93     GNUNET_IDENTITY_cancel (set_op);
94     set_op = NULL;
95   }
96   if (NULL != create_op)
97   {
98     GNUNET_IDENTITY_cancel (create_op);
99     create_op = NULL;
100   }
101   if (NULL != delete_op)
102   {
103     GNUNET_IDENTITY_cancel (delete_op);
104     delete_op = NULL;
105   }
106   GNUNET_IDENTITY_disconnect (sh);
107   sh = NULL;
108 }
109
110
111 /**
112  * Test if we are finished yet.
113  */
114 static void
115 test_finished ()
116 {
117   if ( (NULL == create_op) &&
118        (NULL == delete_op) &&
119        (NULL == set_op) &&
120        (NULL == set_ego) &&
121        (! list) &&
122        (! monitor) )
123     GNUNET_SCHEDULER_shutdown ();
124 }
125
126
127 /**
128  * Deletion operation finished.
129  *
130  * @param cls pointer to operation handle
131  * @param emsg NULL on success, otherwise an error message
132  */
133 static void
134 delete_finished (void *cls,
135                  const char *emsg)
136 {
137   struct GNUNET_IDENTITY_Operation **op = cls;
138
139   *op = NULL;
140   if (NULL != emsg)
141     fprintf (stderr,
142              "%s\n",
143              gettext (emsg));
144   test_finished ();
145 }
146
147
148 /**
149  * Creation operation finished.
150  *
151  * @param cls pointer to operation handle
152  * @param emsg error message, NULL on success
153  */
154 static void
155 create_finished (void *cls,
156                  const char *emsg)
157 {
158   struct GNUNET_IDENTITY_Operation **op = cls;
159
160   *op = NULL;
161   if (NULL != emsg)
162     fprintf (stderr,
163              _("Failed to create ego: %s\n"),
164              emsg);
165   test_finished ();
166 }
167
168
169 /**
170  * Function called by #GNUNET_IDENTITY_set up on completion.
171  *
172  * @param cls NULL
173  * @param emsg error message (NULL on success)
174  */
175 static void
176 set_done (void *cls,
177           const char *emsg)
178 {
179   set_op = NULL;
180   if (NULL != emsg)
181     fprintf (stderr,
182              _("Failed to set default ego: %s\n"),
183              emsg);
184   test_finished ();
185 }
186
187
188 /**
189  * If listing is enabled, prints information about the egos.
190  *
191  * This function is initially called for all egos and then again
192  * whenever a ego's identifier changes or if it is deleted.  At the
193  * end of the initial pass over all egos, the function is once called
194  * with 'NULL' for 'ego'. That does NOT mean that the callback won't
195  * be invoked in the future or that there was an error.
196  *
197  * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
198  * this function is only called ONCE, and 'NULL' being passed in
199  * 'ego' does indicate an error (i.e. name is taken or no default
200  * value is known).  If 'ego' is non-NULL and if '*ctx'
201  * is set in those callbacks, the value WILL be passed to a subsequent
202  * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
203  * that one was not NULL).
204  *
205  * When an identity is renamed, this function is called with the
206  * (known) ego but the NEW identifier.
207  *
208  * When an identity is deleted, this function is called with the
209  * (known) ego and "NULL" for the 'identifier'.  In this case,
210  * the 'ego' is henceforth invalid (and the 'ctx' should also be
211  * cleaned up).
212  *
213  * @param cls closure
214  * @param ego ego handle
215  * @param ctx context for application to store data for this ego
216  *                 (during the lifetime of this process, initially NULL)
217  * @param identifier identifier assigned by the user for this ego,
218  *                   NULL if the user just deleted the ego and it
219  *                   must thus no longer be used
220 */
221 static void
222 print_ego (void *cls,
223            struct GNUNET_IDENTITY_Ego *ego,
224            void **ctx,
225            const char *identifier)
226 {
227   struct GNUNET_CRYPTO_EcdsaPublicKey pk;
228   char *s;
229
230   if ( (NULL != set_ego) &&
231        (NULL != ego) &&
232        (NULL != identifier) &&
233        (0 == strcmp (identifier,
234                      set_ego)) )
235     {
236       set_op = GNUNET_IDENTITY_set (sh,
237                                     set_subsystem,
238                                     ego,
239                                     &set_done,
240                                     NULL);
241       GNUNET_free (set_subsystem);
242       set_subsystem = NULL;
243       GNUNET_free (set_ego);
244       set_ego = NULL;
245     }
246   if ( (NULL == ego) &&
247        (NULL != set_ego) )
248   {
249     fprintf (stderr,
250              "Could not set ego to `%s' for subsystem `%s', ego not known\n",
251              set_ego,
252              set_subsystem);
253     GNUNET_free (set_subsystem);
254     set_subsystem = NULL;
255     GNUNET_free (set_ego);
256     set_ego = NULL;
257   }
258   if ( (NULL == ego) && (! monitor) )
259   {
260     GNUNET_SCHEDULER_shutdown ();
261     return;
262   }
263   if (! (list | monitor))
264     return;
265   if (NULL == ego)
266     return;
267   GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
268   s = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
269   if ( (monitor) || (NULL != identifier) )
270     fprintf (stdout, "%s - %s\n", identifier, s);
271   GNUNET_free (s);
272 }
273
274
275 /**
276  * Main function that will be run by the scheduler.
277  *
278  * @param cls closure
279  * @param args remaining command-line arguments
280  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
281  * @param cfg configuration
282  */
283 static void
284 run (void *cls, char *const *args, const char *cfgfile,
285      const struct GNUNET_CONFIGURATION_Handle *cfg)
286 {
287   if ( (NULL == set_subsystem) ^
288        (NULL == set_ego) )
289   {
290     fprintf (stderr,
291              "Options -e and -s must always be specified together\n");
292     return;
293   }
294   sh = GNUNET_IDENTITY_connect (cfg, &print_ego, NULL);
295   if (NULL != delete_ego)
296     delete_op = GNUNET_IDENTITY_delete (sh,
297                                         delete_ego,
298                                         &delete_finished,
299                                         &delete_op);
300   if (NULL != create_ego)
301     create_op = GNUNET_IDENTITY_create (sh,
302                                         create_ego,
303                                         &create_finished,
304                                         &create_op);
305   GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
306   test_finished ();
307 }
308
309
310 /**
311  * The main function.
312  *
313  * @param argc number of arguments from the command line
314  * @param argv command line arguments
315  * @return 0 ok, 1 on error
316  */
317 int
318 main (int argc, char *const *argv)
319 {
320   int res;
321
322   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
323     {'C', "create", "NAME",
324      gettext_noop ("create ego NAME"),
325      1, &GNUNET_GETOPT_set_string, &create_ego},
326     {'D', "delete", "NAME",
327      gettext_noop ("delete ego NAME "),
328      1, &GNUNET_GETOPT_set_string, &delete_ego},
329     {'d', "display", NULL,
330      gettext_noop ("display all egos"),
331      0, &GNUNET_GETOPT_set_one, &list},
332     {'e', "ego", "NAME",
333      gettext_noop ("set default identity to EGO for a subsystem SUBSYSTEM (use together with -s)"),
334      1, &GNUNET_GETOPT_set_string, &set_ego},
335     {'m', "monitor", NULL,
336      gettext_noop ("run in monitor mode egos"),
337      0, &GNUNET_GETOPT_set_one, &monitor},
338     {'s', "set", "SUBSYSTEM",
339      gettext_noop ("set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)"),
340      1, &GNUNET_GETOPT_set_string, &set_subsystem},
341     GNUNET_GETOPT_OPTION_END
342   };
343
344   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
345     return 2;
346
347   res = GNUNET_PROGRAM_run (argc, argv, "gnunet-identity",
348                             gettext_noop ("Maintain egos"),
349                             options, &run,
350                             NULL);
351   GNUNET_free ((void *) argv);
352
353   if (GNUNET_OK != res)
354     return 1;
355   return 0;
356 }
357
358 /* end of gnunet-identity.c */