Merge remote-tracking branch 'origin/master' into credentials
[oweals/gnunet.git] / src / identity / gnunet-service-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 /**
22  * @file identity/gnunet-service-identity.c
23  * @brief identity management service
24  * @author Christian Grothoff
25  *
26  * The purpose of this service is to manage private keys that
27  * represent the various egos/pseudonyms/identities of a GNUnet user.
28  *
29  * Todo:
30  * - auto-initialze default egos; maybe trigger default
31  *   initializations (such as gnunet-gns-import.sh?)
32  */
33 #include "platform.h"
34 #include "gnunet_util_lib.h"
35 #include "gnunet_constants.h"
36 #include "gnunet_protocols.h"
37 #include "gnunet_statistics_service.h"
38 #include "gnunet_identity_service.h"
39 #include "identity.h"
40
41
42 /**
43  * Information we keep about each ego.
44  */
45 struct Ego
46 {
47
48   /**
49    * We keep egos in a DLL.
50    */
51   struct Ego *next;
52
53   /**
54    * We keep egos in a DLL.
55    */
56   struct Ego *prev;
57
58   /**
59    * Private key of the ego.
60    */
61   struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
62
63   /**
64    * String identifier for the ego.
65    */
66   char *identifier;
67
68 };
69
70
71 /**
72  * Handle to our current configuration.
73  */
74 static const struct GNUNET_CONFIGURATION_Handle *cfg;
75
76 /**
77  * Handle to subsystem configuration which for each subsystem contains
78  * the name of the default ego.
79  */
80 static struct GNUNET_CONFIGURATION_Handle *subsystem_cfg;
81
82 /**
83  * Handle to the statistics service.
84  */
85 static struct GNUNET_STATISTICS_Handle *stats;
86
87 /**
88  * Notification context, simplifies client broadcasts.
89  */
90 static struct GNUNET_NotificationContext *nc;
91
92 /**
93  * Directory where we store the identities.
94  */
95 static char *ego_directory;
96
97 /**
98  * Configuration file name where subsystem information is kept.
99  */
100 static char *subsystem_cfg_file;
101
102 /**
103  * Head of DLL of all egos.
104  */
105 static struct Ego *ego_head;
106
107 /**
108  * Tail of DLL of all egos.
109  */
110 static struct Ego *ego_tail;
111
112
113 /**
114  * Get the name of the file we use to store a given ego.
115  *
116  * @param ego ego for which we need the filename
117  * @return full filename for the given ego
118  */
119 static char *
120 get_ego_filename (struct Ego *ego)
121 {
122   char *filename;
123
124   GNUNET_asprintf (&filename,
125                    "%s%s%s",
126                    ego_directory,
127                    DIR_SEPARATOR_STR,
128                    ego->identifier);
129   return filename;
130 }
131
132 /**
133  * Called whenever a client is disconnected.
134  *
135  * @param cls closure
136  * @param client identification of the client
137  * @param app_ctx @a client
138  */
139 static void
140 client_disconnect_cb (void *cls,
141                       struct GNUNET_SERVICE_Client *client,
142                       void *app_ctx)
143 {
144   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
145               "Client %p disconnected\n",
146               client);
147 }
148
149
150 /**
151  * Add a client to our list of active clients.
152  *
153  * @param cls NULL
154  * @param client client to add
155  * @param mq message queue for @a client
156  * @return internal namestore client structure for this client
157  */
158 static void *
159 client_connect_cb (void *cls,
160                    struct GNUNET_SERVICE_Client *client,
161                    struct GNUNET_MQ_Handle *mq)
162 {
163   return client;
164 }
165
166 /**
167  * Task run during shutdown.
168  *
169  * @param cls unused
170  */
171 static void
172 shutdown_task (void *cls)
173 {
174   struct Ego *e;
175
176   if (NULL != nc)
177   {
178     GNUNET_notification_context_destroy (nc);
179     nc = NULL;
180   }
181   if (NULL != stats)
182   {
183     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
184     stats = NULL;
185   }
186   GNUNET_CONFIGURATION_destroy (subsystem_cfg);
187   subsystem_cfg = NULL;
188   GNUNET_free (subsystem_cfg_file);
189   subsystem_cfg_file = NULL;
190   GNUNET_free (ego_directory);
191   ego_directory = NULL;
192   while (NULL != (e = ego_head))
193   {
194     GNUNET_CONTAINER_DLL_remove (ego_head, ego_tail, e);
195     GNUNET_free (e->pk);
196     GNUNET_free (e->identifier);
197     GNUNET_free (e);
198   }
199 }
200
201
202 /**
203  * Send a result code back to the client.
204  *
205  * @param client client that should receive the result code
206  * @param result_code code to transmit
207  * @param emsg error message to include (or NULL for none)
208  */
209 static void
210 send_result_code (struct GNUNET_SERVICE_Client *client,
211                   uint32_t result_code,
212                   const char *emsg)
213 {
214   struct ResultCodeMessage *rcm;
215   struct GNUNET_MQ_Envelope *env;
216   size_t elen;
217
218   if (NULL == emsg)
219     elen = 0;
220   else
221     elen = strlen (emsg) + 1;
222   env = GNUNET_MQ_msg_extra (rcm,
223                              elen,
224                              GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE);
225   rcm->result_code = htonl (result_code);
226   if (0 < elen)
227     GNUNET_memcpy (&rcm[1], emsg, elen);
228   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
229               "Sending result %d (%s) to client\n",
230               (int) result_code,
231               emsg);
232   GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
233 }
234
235
236 /**
237  * Create an update message with information about the current state of an ego.
238  *
239  * @param ego ego to create message for
240  * @return corresponding update message
241  */
242 static struct GNUNET_MQ_Envelope *
243 create_update_message (struct Ego *ego)
244 {
245   struct UpdateMessage *um;
246   struct GNUNET_MQ_Envelope *env;
247   size_t name_len;
248
249   name_len = (NULL == ego->identifier) ? 0 : (strlen (ego->identifier) + 1);
250   env = GNUNET_MQ_msg_extra (um,
251                              name_len,
252                              GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE);
253   um->name_len = htons (name_len);
254   um->end_of_list = htons (GNUNET_NO);
255   um->private_key = *ego->pk;
256   GNUNET_memcpy (&um[1], ego->identifier, name_len);
257   return env;
258 }
259
260
261 /**
262  * Create a set default message with information about the current state of an ego.
263  *
264  * @param ego ego to create message for
265  * @param servicename name of the service to provide in the message
266  * @return corresponding set default message
267  */
268 static struct GNUNET_MQ_Envelope *
269 create_set_default_message (struct Ego *ego,
270                             const char *servicename)
271 {
272   struct SetDefaultMessage *sdm;
273   struct GNUNET_MQ_Envelope *env;
274   size_t name_len;
275
276   name_len = (NULL == servicename) ? 0 : (strlen (servicename) + 1);
277   env = GNUNET_MQ_msg_extra (sdm,
278                              name_len,
279                              GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT);
280   sdm->name_len = htons (name_len);
281   sdm->reserved = htons (0);
282   sdm->private_key = *ego->pk;
283   GNUNET_memcpy (&sdm[1], servicename, name_len);
284   return env;
285 }
286
287
288 /**
289  * Handler for START message from client, sends information
290  * about all identities to the client immediately and
291  * adds the client to the notification context for future
292  * updates.
293  *
294  * @param cls unused
295  * @param client who sent the message
296  * @param message the message received
297  */
298 static void
299 handle_start_message (void *cls,
300                       const struct GNUNET_MessageHeader *message)
301 {
302   struct UpdateMessage *ume;
303   struct GNUNET_SERVICE_Client *client = cls;
304   struct GNUNET_MQ_Envelope *env;
305   struct Ego *ego;
306
307   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
308               "Received START message from client\n");
309   GNUNET_SERVICE_client_mark_monitor (client);
310   GNUNET_SERVICE_client_disable_continue_warning (client);
311   GNUNET_notification_context_add (nc,
312                                    GNUNET_SERVICE_client_get_mq(client));
313   for (ego = ego_head; NULL != ego; ego = ego->next)
314   {
315     env = create_update_message (ego);
316     GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(client), env);
317   }
318   env = GNUNET_MQ_msg_extra (ume,
319                              0,
320                              GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE);
321   ume->end_of_list = htons (GNUNET_YES);
322   ume->name_len = htons (0);
323   GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(client), env);
324   GNUNET_SERVICE_client_continue (client);
325 }
326
327 /**
328  * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT message
329  *
330  * @param cls client sending the message
331  * @param msg message of type `struct GetDefaultMessage`
332  * @return #GNUNET_OK if @a msg is well-formed
333  */
334 static int
335 check_get_default_message (void *cls,
336                            const struct GetDefaultMessage *msg)
337 {
338   uint16_t size;
339   uint16_t name_len;
340   const char *name;
341
342   size = ntohs (msg->header.size);
343   if (size <= sizeof (struct GetDefaultMessage))
344   {
345     GNUNET_break (0);
346     return GNUNET_SYSERR;
347   }
348   name = (const char *) &msg[1];
349   name_len = ntohs (msg->name_len);
350   if ( (name_len + sizeof (struct GetDefaultMessage) != size) ||
351        (0 != ntohs (msg->reserved)) ||
352        ('\0' != name[name_len - 1]) )
353   {
354     GNUNET_break (0);
355     return GNUNET_SYSERR;
356   }
357   return GNUNET_OK;
358 }
359
360
361 /**
362  * Handler for GET_DEFAULT message from client, returns
363  * default identity for some service.
364  *
365  * @param cls unused
366  * @param client who sent the message
367  * @param message the message received
368  */
369 static void
370 handle_get_default_message (void *cls,
371                             const struct GetDefaultMessage *gdm)
372 {
373   struct GNUNET_MQ_Envelope *env;
374   struct GNUNET_SERVICE_Client *client = cls;
375   struct Ego *ego;
376   const char *name;
377   char *identifier;
378
379
380   name = (const char *) &gdm[1];
381   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
382               "Received GET_DEFAULT for service `%s' from client\n",
383               name);
384   if (GNUNET_OK !=
385       GNUNET_CONFIGURATION_get_value_string (subsystem_cfg,
386                                              name,
387                                              "DEFAULT_IDENTIFIER",
388                                              &identifier))
389   {
390     send_result_code (client, 1, gettext_noop ("no default known"));
391     GNUNET_SERVICE_client_continue (client);
392     return;
393   }
394   for (ego = ego_head; NULL != ego; ego = ego->next)
395   {
396     if (0 == strcmp (ego->identifier,
397                      identifier))
398     {
399       env = create_set_default_message (ego,
400                                         name);
401       GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
402       GNUNET_SERVICE_client_continue (client);
403       GNUNET_free (identifier);
404       return;
405     }
406   }
407   GNUNET_free (identifier);
408   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
409               "Failed to find ego `%s'\n",
410               name);
411   send_result_code (client, 1,
412                     gettext_noop ("default configured, but ego unknown (internal error)"));
413   GNUNET_SERVICE_client_continue (client);
414 }
415
416
417 /**
418  * Compare the given two private keys for equality.
419  *
420  * @param pk1 one private key
421  * @param pk2 another private key
422  * @return 0 if the keys are equal
423  */
424 static int
425 key_cmp (const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk1,
426          const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk2)
427 {
428   return memcmp (pk1, pk2, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
429 }
430
431 /**
432  * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT message
433  *
434  * @param cls client sending the message
435  * @param msg message of type `struct SetDefaultMessage`
436  * @return #GNUNET_OK if @a msg is well-formed
437  */
438 static int
439 check_set_default_message (void *cls,
440                            const struct SetDefaultMessage *msg)
441 {
442   uint16_t size;
443   uint16_t name_len;
444   const char *str;
445
446   size = ntohs (msg->header.size);
447   if (size <= sizeof (struct SetDefaultMessage))
448   {
449     GNUNET_break (0);
450     return GNUNET_SYSERR;
451   }
452   name_len = ntohs (msg->name_len);
453   GNUNET_break (0 == ntohs (msg->reserved));
454   if (name_len + sizeof (struct SetDefaultMessage) != size)
455   {
456     GNUNET_break (0);
457     return GNUNET_SYSERR;
458   }
459   str = (const char *) &msg[1];
460   if ('\0' != str[name_len - 1])
461   {
462     GNUNET_break (0);
463     return GNUNET_SYSERR;
464   }
465   return GNUNET_OK;
466 }
467
468 /**
469  * Handler for SET_DEFAULT message from client, updates
470  * default identity for some service.
471  *
472  * @param cls unused
473  * @param client who sent the message
474  * @param message the message received
475  */
476 static void
477 handle_set_default_message (void *cls,
478                             const struct SetDefaultMessage *sdm)
479 {
480   struct Ego *ego;
481   struct GNUNET_SERVICE_Client *client = cls;
482   const char *str;
483
484   str = (const char *) &sdm[1];
485   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
486               "Received SET_DEFAULT for service `%s' from client\n",
487               str);
488   for (ego = ego_head; NULL != ego; ego = ego->next)
489   {
490     if (0 == key_cmp (ego->pk,
491                       &sdm->private_key))
492     {
493       GNUNET_CONFIGURATION_set_value_string (subsystem_cfg,
494                                              str,
495                                              "DEFAULT_IDENTIFIER",
496                                              ego->identifier);
497       if (GNUNET_OK !=
498           GNUNET_CONFIGURATION_write (subsystem_cfg,
499                                       subsystem_cfg_file))
500         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
501                     _("Failed to write subsystem default identifier map to `%s'.\n"),
502                     subsystem_cfg_file);
503       send_result_code (client, 0, NULL);
504       GNUNET_SERVICE_client_continue (client);
505       return;
506     }
507   }
508   send_result_code (client, 1, _("Unknown ego specified for service (internal error)"));
509   GNUNET_SERVICE_client_continue (client);
510 }
511
512
513 /**
514  * Send an updated message for the given ego to all listeners.
515  *
516  * @param ego ego to send the update for
517  */
518 static void
519 notify_listeners (struct Ego *ego)
520 {
521   struct UpdateMessage *um;
522   size_t name_len;
523
524   name_len = (NULL == ego->identifier) ? 0 : (strlen (ego->identifier) + 1);
525   um = GNUNET_malloc (sizeof (struct UpdateMessage) + name_len);
526   um->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE);
527   um->header.size = htons (sizeof (struct UpdateMessage) + name_len);
528   um->name_len = htons (name_len);
529   um->end_of_list = htons (GNUNET_NO);
530   um->private_key = *ego->pk;
531   GNUNET_memcpy (&um[1], ego->identifier, name_len);
532   GNUNET_notification_context_broadcast (nc,
533                                          &um->header,
534                                          GNUNET_NO);
535   GNUNET_free (um);
536 }
537
538 /**
539  * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_CREATE message
540  *
541  * @param cls client sending the message
542  * @param msg message of type `struct CreateRequestMessage`
543  * @return #GNUNET_OK if @a msg is well-formed
544  */
545 static int
546 check_create_message (void *cls,
547                       const struct CreateRequestMessage *msg)
548 {
549   
550   uint16_t size;
551   uint16_t name_len;
552   const char *str;
553
554   size = ntohs (msg->header.size);
555   if (size <= sizeof (struct CreateRequestMessage))
556   {
557     GNUNET_break (0);
558     return GNUNET_SYSERR;
559   }
560   name_len = ntohs (msg->name_len);
561   GNUNET_break (0 == ntohs (msg->reserved));
562   if (name_len + sizeof (struct CreateRequestMessage) != size)
563   {
564     GNUNET_break (0);
565     return GNUNET_SYSERR;
566   }
567   str = (const char *) &msg[1];
568   if ('\0' != str[name_len - 1])
569   {
570     GNUNET_break (0);
571     return GNUNET_SYSERR;
572   }
573   return GNUNET_OK;
574
575
576 /**
577  * Handler for CREATE message from client, creates
578  * new identity.
579  *
580  * @param cls unused
581  * @param client who sent the message
582  * @param message the message received
583  */
584 static void
585 handle_create_message (void *cls,
586                        const struct CreateRequestMessage *crm)
587 {
588   struct GNUNET_SERVICE_Client *client = cls;
589   struct Ego *ego;
590   const char *str;
591   char *fn;
592
593   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
594               "Received CREATE message from client\n");
595   str = (const char *) &crm[1];
596   for (ego = ego_head; NULL != ego; ego = ego->next)
597   {
598     if (0 == strcmp (ego->identifier,
599                      str))
600     {
601       send_result_code (client, 1, gettext_noop ("identifier already in use for another ego"));
602       GNUNET_SERVICE_client_continue (client);
603       return;
604     }
605   }
606   ego = GNUNET_new (struct Ego);
607   ego->pk = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
608   *ego->pk = crm->private_key;
609   ego->identifier = GNUNET_strdup (str);
610   GNUNET_CONTAINER_DLL_insert (ego_head,
611                                ego_tail,
612                                ego);
613   send_result_code (client, 0, NULL);
614   fn = get_ego_filename (ego);
615   (void) GNUNET_DISK_directory_create_for_file (fn);
616   if (sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey) !=
617       GNUNET_DISK_fn_write (fn,
618                             &crm->private_key,
619                             sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
620                             GNUNET_DISK_PERM_USER_READ |
621                             GNUNET_DISK_PERM_USER_WRITE))
622     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
623                               "write", fn);
624   GNUNET_free (fn);
625   notify_listeners (ego);
626   GNUNET_SERVICE_client_continue (client);
627 }
628
629
630 /**
631  * Closure for 'handle_ego_rename'.
632  */
633 struct RenameContext
634 {
635   /**
636    * Old name.
637    */
638   const char *old_name;
639
640   /**
641    * New name.
642    */
643   const char *new_name;
644 };
645
646 /**
647  * An ego was renamed; rename it in all subsystems where it is
648  * currently set as the default.
649  *
650  * @param cls the 'struct RenameContext'
651  * @param section a section in the configuration to process
652  */
653 static void
654 handle_ego_rename (void *cls,
655                    const char *section)
656 {
657   struct RenameContext *rc = cls;
658   char *id;
659
660   if (GNUNET_OK !=
661       GNUNET_CONFIGURATION_get_value_string (subsystem_cfg,
662                                              section,
663                                              "DEFAULT_IDENTIFIER",
664                                              &id))
665     return;
666   if (0 != strcmp (id, rc->old_name))
667   {
668     GNUNET_free (id);
669     return;
670   }
671   GNUNET_CONFIGURATION_set_value_string (subsystem_cfg,
672                                          section,
673                                          "DEFAULT_IDENTIFIER",
674                                          rc->new_name);
675   GNUNET_free (id);
676 }
677
678 /**
679  * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_RENAME message
680  *
681  * @param cls client sending the message
682  * @param msg message of type `struct RenameMessage`
683  * @return #GNUNET_OK if @a msg is well-formed
684  */
685 static int
686 check_rename_message (void *cls,
687                       const struct RenameMessage *msg)
688 {
689   uint16_t size;
690   uint16_t old_name_len;
691   uint16_t new_name_len;
692   const char *old_name;
693   const char *new_name;
694
695   size = ntohs (msg->header.size);
696   if (size <= sizeof (struct RenameMessage))
697   {
698     GNUNET_break (0);
699     return GNUNET_SYSERR;
700   }
701   old_name_len = ntohs (msg->old_name_len);
702   new_name_len = ntohs (msg->new_name_len);
703   old_name = (const char *) &msg[1];
704   new_name = &old_name[old_name_len];
705   if ( (old_name_len + new_name_len + sizeof (struct RenameMessage) != size) ||
706        ('\0' != old_name[old_name_len - 1]) ||
707        ('\0' != new_name[new_name_len - 1]) )
708   {
709     GNUNET_break (0);
710     return GNUNET_SYSERR;
711   }
712
713   return GNUNET_OK;
714 }
715  
716
717 /**
718  * Handler for RENAME message from client, creates
719  * new identity.
720  *
721  * @param cls unused
722  * @param client who sent the message
723  * @param message the message received
724  */
725 static void
726 handle_rename_message (void *cls,
727                        const struct RenameMessage *rm)
728 {
729   uint16_t old_name_len;
730   struct Ego *ego;
731   const char *old_name;
732   const char *new_name;
733   struct RenameContext rename_ctx;
734   struct GNUNET_SERVICE_Client *client = cls;
735   char *fn_old;
736   char *fn_new;
737
738   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
739               "Received RENAME message from client\n");
740   old_name_len = ntohs (rm->old_name_len);
741   old_name = (const char *) &rm[1];
742   new_name = &old_name[old_name_len];
743
744   /* check if new name is already in use */
745   for (ego = ego_head; NULL != ego; ego = ego->next)
746   {
747     if (0 == strcmp (ego->identifier,
748                      new_name))
749     {
750       send_result_code (client, 1, gettext_noop ("target name already exists"));
751       GNUNET_SERVICE_client_continue (client);
752       return;
753     }
754   }
755
756   /* locate old name and, if found, perform rename */
757   for (ego = ego_head; NULL != ego; ego = ego->next)
758   {
759     if (0 == strcmp (ego->identifier,
760                      old_name))
761     {
762       fn_old = get_ego_filename (ego);
763       GNUNET_free (ego->identifier);
764       rename_ctx.old_name = old_name;
765       rename_ctx.new_name = new_name;
766       GNUNET_CONFIGURATION_iterate_sections (subsystem_cfg,
767                                              &handle_ego_rename,
768                                              &rename_ctx);
769       if (GNUNET_OK !=
770           GNUNET_CONFIGURATION_write (subsystem_cfg,
771                                       subsystem_cfg_file))
772         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
773                     _("Failed to write subsystem default identifier map to `%s'.\n"),
774                     subsystem_cfg_file);
775       ego->identifier = GNUNET_strdup (new_name);
776       fn_new = get_ego_filename (ego);
777       if (0 != RENAME (fn_old, fn_new))
778         GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "rename", fn_old);
779       GNUNET_free (fn_old);
780       GNUNET_free (fn_new);
781       notify_listeners (ego);
782       send_result_code (client, 0, NULL);
783       GNUNET_SERVICE_client_continue (client);
784       return;
785     }
786   }
787
788   /* failed to locate old name */
789   send_result_code (client, 1, gettext_noop ("no matching ego found"));
790   GNUNET_SERVICE_client_continue (client);
791 }
792
793
794 /**
795  * An ego was removed, remove it from all subsystems where it is
796  * currently set as the default.
797  *
798  * @param cls name of the removed ego (const char *)
799  * @param section a section in the configuration to process
800  */
801 static void
802 handle_ego_delete (void *cls,
803                    const char *section)
804 {
805   const char *identifier = cls;
806   char *id;
807
808   if (GNUNET_OK !=
809       GNUNET_CONFIGURATION_get_value_string (subsystem_cfg,
810                                              section,
811                                              "DEFAULT_IDENTIFIER",
812                                              &id))
813     return;
814   if (0 != strcmp (id, identifier))
815   {
816     GNUNET_free (id);
817     return;
818   }
819   GNUNET_CONFIGURATION_set_value_string (subsystem_cfg,
820                                          section,
821                                          "DEFAULT_IDENTIFIER",
822                                          NULL);
823   GNUNET_free (id);
824 }
825
826 /**
827  * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_DELETE message
828  *
829  * @param cls client sending the message
830  * @param msg message of type `struct DeleteMessage`
831  * @return #GNUNET_OK if @a msg is well-formed
832  */
833 static int
834 check_delete_message (void *cls,
835                       const struct DeleteMessage *msg)
836 {
837   uint16_t size;
838   uint16_t name_len;
839   const char *name;
840
841   size = ntohs (msg->header.size);
842   if (size <= sizeof (struct DeleteMessage))
843   {
844     GNUNET_break (0);
845     return GNUNET_SYSERR;
846   }
847   name = (const char *) &msg[1];
848   name_len = ntohs (msg->name_len);
849   if ( (name_len + sizeof (struct DeleteMessage) != size) ||
850        (0 != ntohs (msg->reserved)) ||
851        ('\0' != name[name_len - 1]) )
852   {
853     GNUNET_break (0);
854     return GNUNET_SYSERR;
855   }
856   return GNUNET_OK;
857 }
858
859
860 /**
861  * Handler for DELETE message from client, creates
862  * new identity.
863  *
864  * @param cls unused
865  * @param client who sent the message
866  * @param message the message received
867  */
868 static void
869 handle_delete_message (void *cls,
870                        const struct DeleteMessage *dm)
871 {
872   struct Ego *ego;
873   const char *name;
874   char *fn;
875   struct GNUNET_SERVICE_Client *client = cls;
876
877   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
878               "Received DELETE message from client\n");
879   name = (const char *) &dm[1];
880   for (ego = ego_head; NULL != ego; ego = ego->next)
881   {
882     if (0 == strcmp (ego->identifier,
883                      name))
884     {
885       GNUNET_CONTAINER_DLL_remove (ego_head,
886                                    ego_tail,
887                                    ego);
888       GNUNET_CONFIGURATION_iterate_sections (subsystem_cfg,
889                                              &handle_ego_delete,
890                                              ego->identifier);
891       if (GNUNET_OK !=
892           GNUNET_CONFIGURATION_write (subsystem_cfg,
893                                       subsystem_cfg_file))
894         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
895                     _("Failed to write subsystem default identifier map to `%s'.\n"),
896                     subsystem_cfg_file);
897       fn = get_ego_filename (ego);
898       if (0 != UNLINK (fn))
899         GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn);
900       GNUNET_free (fn);
901       GNUNET_free (ego->identifier);
902       ego->identifier = NULL;
903       notify_listeners (ego);
904       GNUNET_free (ego->pk);
905       GNUNET_free (ego);
906       send_result_code (client, 0, NULL);
907       GNUNET_SERVICE_client_continue (client);
908       return;
909     }
910   }
911
912   send_result_code (client, 1, gettext_noop ("no matching ego found"));
913   GNUNET_SERVICE_client_continue (client);
914 }
915
916
917 /**
918  * Process the given file from the "EGODIR".  Parses the file
919  * and creates the respective 'struct Ego' in memory.
920  *
921  * @param cls NULL
922  * @param filename name of the file to parse
923  * @return #GNUNET_OK to continue to iterate,
924  *  #GNUNET_NO to stop iteration with no error,
925  *  #GNUNET_SYSERR to abort iteration with error!
926  */
927 static int
928 process_ego_file (void *cls,
929                   const char *filename)
930 {
931   struct Ego *ego;
932   const char *fn;
933
934   fn = strrchr (filename, (int) DIR_SEPARATOR);
935   if (NULL == fn)
936   {
937     GNUNET_break (0);
938     return GNUNET_OK;
939   }
940   ego = GNUNET_new (struct Ego);
941   ego->pk = GNUNET_CRYPTO_ecdsa_key_create_from_file (filename);
942   if (NULL == ego->pk)
943   {
944     GNUNET_free (ego);
945     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
946                 _("Failed to parse ego information in `%s'\n"),
947                 filename);
948     return GNUNET_OK;
949   }
950   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
951               "Loaded ego `%s'\n",
952               fn + 1);
953   ego->identifier = GNUNET_strdup (fn + 1);
954   GNUNET_CONTAINER_DLL_insert (ego_head,
955                                ego_tail,
956                                ego);
957   return GNUNET_OK;
958 }
959
960
961 /**
962  * Handle network size estimate clients.
963  *
964  * @param cls closure
965  * @param server the initialized server
966  * @param c configuration to use
967  */
968 static void
969 run (void *cls,
970      const struct GNUNET_CONFIGURATION_Handle *c,
971      struct GNUNET_SERVICE_Handle *service)
972 {
973   cfg = c;
974   nc = GNUNET_notification_context_create (1);
975   if (GNUNET_OK !=
976       GNUNET_CONFIGURATION_get_value_filename (cfg, "identity",
977                                                "EGODIR",
978                                                &ego_directory))
979   {
980     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "identity", "EGODIR");
981     GNUNET_SCHEDULER_shutdown ();
982     return;
983   }
984   if (GNUNET_OK !=
985       GNUNET_CONFIGURATION_get_value_filename (cfg, "identity",
986                                                "SUBSYSTEM_CFG",
987                                                &subsystem_cfg_file))
988   {
989     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "identity", "SUBSYSTEM_CFG");
990     GNUNET_SCHEDULER_shutdown ();
991     return;
992   }
993   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
994               "Loading subsystem configuration `%s'\n",
995               subsystem_cfg_file);
996   subsystem_cfg = GNUNET_CONFIGURATION_create ();
997   if ( (GNUNET_YES ==
998         GNUNET_DISK_file_test (subsystem_cfg_file)) &&
999        (GNUNET_OK !=
1000         GNUNET_CONFIGURATION_parse (subsystem_cfg,
1001                                     subsystem_cfg_file)) )
1002   {
1003     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1004                 _("Failed to parse subsystem identity configuration file `%s'\n"),
1005                 subsystem_cfg_file);
1006     GNUNET_SCHEDULER_shutdown ();
1007     return;
1008   }
1009   stats = GNUNET_STATISTICS_create ("identity", cfg);
1010   if (GNUNET_OK !=
1011       GNUNET_DISK_directory_create (ego_directory))
1012   {
1013     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1014                 _("Failed to create directory `%s' for storing egos\n"),
1015                 ego_directory);
1016   }
1017   GNUNET_DISK_directory_scan (ego_directory,
1018                               &process_ego_file,
1019                               NULL);
1020   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1021                                  NULL);
1022 }
1023
1024
1025 /**
1026  * Define "main" method using service macro.
1027  */
1028 GNUNET_SERVICE_MAIN
1029 ("identity",
1030  GNUNET_SERVICE_OPTION_NONE,
1031  &run,
1032  &client_connect_cb,
1033  &client_disconnect_cb,
1034  NULL,
1035  GNUNET_MQ_hd_fixed_size (start_message,
1036                           GNUNET_MESSAGE_TYPE_IDENTITY_START,
1037                           struct GNUNET_MessageHeader,
1038                           NULL),
1039  GNUNET_MQ_hd_var_size (get_default_message,
1040                         GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT,
1041                         struct GetDefaultMessage,
1042                         NULL),
1043  GNUNET_MQ_hd_var_size (set_default_message,
1044                         GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT,
1045                         struct SetDefaultMessage,
1046                         NULL),
1047  GNUNET_MQ_hd_var_size (create_message,
1048                         GNUNET_MESSAGE_TYPE_IDENTITY_CREATE,
1049                         struct CreateRequestMessage,
1050                         NULL),
1051  GNUNET_MQ_hd_var_size (rename_message,
1052                         GNUNET_MESSAGE_TYPE_IDENTITY_RENAME,
1053                         struct RenameMessage,
1054                         NULL),
1055  GNUNET_MQ_hd_var_size (delete_message,
1056                         GNUNET_MESSAGE_TYPE_IDENTITY_DELETE,
1057                         struct DeleteMessage,
1058                         NULL),
1059  GNUNET_MQ_handler_end());
1060
1061
1062
1063 /* end of gnunet-service-identity.c */