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