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