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