2 This file is part of GNUnet.
3 Copyright (C) 2013 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file identity/gnunet-service-identity.c
23 * @brief identity management service
24 * @author Christian Grothoff
26 * The purpose of this service is to manage private keys that
27 * represent the various egos/pseudonyms/identities of a GNUnet user.
30 * - auto-initialze default egos; maybe trigger default
31 * initializations (such as gnunet-gns-import.sh?)
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"
43 * Information we keep about each ego.
49 * We keep egos in a DLL.
54 * We keep egos in a DLL.
59 * Private key of the ego.
61 struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
64 * String identifier for the ego.
71 * Handle to our current configuration.
73 static const struct GNUNET_CONFIGURATION_Handle *cfg;
76 * Handle to subsystem configuration which for each subsystem contains
77 * the name of the default ego.
79 static struct GNUNET_CONFIGURATION_Handle *subsystem_cfg;
82 * Handle to the statistics service.
84 static struct GNUNET_STATISTICS_Handle *stats;
87 * Notification context, simplifies client broadcasts.
89 static struct GNUNET_NotificationContext *nc;
92 * Directory where we store the identities.
94 static char *ego_directory;
97 * Configuration file name where subsystem information is kept.
99 static char *subsystem_cfg_file;
102 * Head of DLL of all egos.
104 static struct Ego *ego_head;
107 * Tail of DLL of all egos.
109 static struct Ego *ego_tail;
113 * Get the name of the file we use to store a given ego.
115 * @param ego ego for which we need the filename
116 * @return full filename for the given ego
119 get_ego_filename (struct Ego *ego)
123 GNUNET_asprintf (&filename,
132 * Called whenever a client is disconnected.
135 * @param client identification of the client
136 * @param app_ctx @a client
139 client_disconnect_cb (void *cls,
140 struct GNUNET_SERVICE_Client *client,
143 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
148 * Add a client to our list of active clients.
151 * @param client client to add
152 * @param mq message queue for @a client
153 * @return internal namestore client structure for this client
156 client_connect_cb (void *cls,
157 struct GNUNET_SERVICE_Client *client,
158 struct GNUNET_MQ_Handle *mq)
164 * Task run during shutdown.
169 shutdown_task (void *cls)
175 GNUNET_notification_context_destroy (nc);
180 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
183 GNUNET_CONFIGURATION_destroy (subsystem_cfg);
184 subsystem_cfg = NULL;
185 GNUNET_free (subsystem_cfg_file);
186 subsystem_cfg_file = NULL;
187 GNUNET_free (ego_directory);
188 ego_directory = NULL;
189 while (NULL != (e = ego_head))
191 GNUNET_CONTAINER_DLL_remove (ego_head, ego_tail, e);
193 GNUNET_free (e->identifier);
200 * Send a result code back to the client.
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)
207 send_result_code (struct GNUNET_SERVICE_Client *client,
208 uint32_t result_code,
211 struct ResultCodeMessage *rcm;
212 struct GNUNET_MQ_Envelope *env;
218 elen = strlen (emsg) + 1;
220 GNUNET_MQ_msg_extra (rcm, elen, GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE);
221 rcm->result_code = htonl (result_code);
223 GNUNET_memcpy (&rcm[1], emsg, elen);
224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
225 "Sending result %d (%s) to client\n",
228 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
233 * Create an update message with information about the current state of an ego.
235 * @param ego ego to create message for
236 * @return corresponding update message
238 static struct GNUNET_MQ_Envelope *
239 create_update_message (struct Ego *ego)
241 struct UpdateMessage *um;
242 struct GNUNET_MQ_Envelope *env;
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);
256 * Create a set default message with information about the current state of an ego.
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
262 static struct GNUNET_MQ_Envelope *
263 create_set_default_message (struct Ego *ego, const char *servicename)
265 struct SetDefaultMessage *sdm;
266 struct GNUNET_MQ_Envelope *env;
269 name_len = (NULL == servicename) ? 0 : (strlen (servicename) + 1);
270 env = GNUNET_MQ_msg_extra (sdm,
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);
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
287 * @param cls a `struct GNUNET_SERVICE_Client *`
288 * @param message the message received
291 handle_start_message (void *cls, const struct GNUNET_MessageHeader *message)
293 struct GNUNET_SERVICE_Client *client = cls;
294 struct UpdateMessage *ume;
295 struct GNUNET_MQ_Envelope *env;
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)
304 env = create_update_message (ego);
305 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
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);
316 * Handler for LOOKUP message from client, sends information
317 * about ONE identity to the client immediately.
320 * @param message the message received
321 * @return #GNUNET_SYSERR if message was ill-formed
324 check_lookup_message (void *cls, const struct LookupMessage *message)
326 GNUNET_MQ_check_zero_termination (message);
332 * Handler for LOOKUP message from client, sends information
333 * about ONE identity to the client immediately.
335 * @param cls a `struct GNUNET_SERVICE_Client *`
336 * @param message the message received
339 handle_lookup_message (void *cls, const struct LookupMessage *message)
341 struct GNUNET_SERVICE_Client *client = cls;
343 struct GNUNET_MQ_Envelope *env;
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)
350 if (0 != strcasecmp (name, ego->identifier))
352 env = create_update_message (ego);
353 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
354 GNUNET_SERVICE_client_continue (client);
357 send_result_code (client, 0, "ego not found");
358 GNUNET_SERVICE_client_continue (client);
363 * Handler for LOOKUP message from client, sends information
364 * about ONE identity to the client immediately.
367 * @param message the message received
368 * @return #GNUNET_SYSERR if message was ill-formed
371 check_lookup_by_suffix_message (void *cls, const struct LookupMessage *message)
373 GNUNET_MQ_check_zero_termination (message);
379 * Handler for LOOKUP_BY_SUFFIX message from client, sends information
380 * about ONE identity to the client immediately.
382 * @param cls a `struct GNUNET_SERVICE_Client *`
383 * @param message the message received
386 handle_lookup_by_suffix_message (void *cls, const struct LookupMessage *message)
388 struct GNUNET_SERVICE_Client *client = cls;
390 struct GNUNET_MQ_Envelope *env;
393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
394 "Received LOOKUP_BY_SUFFIX message from client\n");
395 name = (const char *) &message[1];
397 for (struct Ego *ego = ego_head; NULL != ego; ego = ego->next)
400 if ((strlen (ego->identifier) <= strlen (name)) &&
401 (0 == strcmp (ego->identifier,
402 &name[strlen (name) - strlen (ego->identifier)])) &&
403 ((strlen (name) == strlen (ego->identifier)) ||
404 ('.' == name[strlen (name) - strlen (ego->identifier) - 1])) &&
405 ((NULL == lprefix) ||
406 (strlen (ego->identifier) > strlen (lprefix->identifier))))
408 /* found better match, update! */
414 env = create_update_message (lprefix);
415 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
416 GNUNET_SERVICE_client_continue (client);
419 send_result_code (client, 0, "ego not found");
420 GNUNET_SERVICE_client_continue (client);
425 * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT message
427 * @param cls client sending the message
428 * @param msg message of type `struct GetDefaultMessage`
429 * @return #GNUNET_OK if @a msg is well-formed
432 check_get_default_message (void *cls, const struct GetDefaultMessage *msg)
438 size = ntohs (msg->header.size);
439 if (size <= sizeof (struct GetDefaultMessage))
442 return GNUNET_SYSERR;
444 name = (const char *) &msg[1];
445 name_len = ntohs (msg->name_len);
446 if ((name_len + sizeof (struct GetDefaultMessage) != size) ||
447 (0 != ntohs (msg->reserved)) || ('\0' != name[name_len - 1]))
450 return GNUNET_SYSERR;
457 * Handler for GET_DEFAULT message from client, returns
458 * default identity for some service.
461 * @param client who sent the message
462 * @param message the message received
465 handle_get_default_message (void *cls, const struct GetDefaultMessage *gdm)
467 struct GNUNET_MQ_Envelope *env;
468 struct GNUNET_SERVICE_Client *client = cls;
474 name = GNUNET_strdup ((const char *) &gdm[1]);
475 GNUNET_STRINGS_utf8_tolower ((const char *) &gdm[1], name);
476 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
477 "Received GET_DEFAULT for service `%s' from client\n",
479 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (subsystem_cfg,
481 "DEFAULT_IDENTIFIER",
484 send_result_code (client, 1, gettext_noop ("no default known"));
485 GNUNET_SERVICE_client_continue (client);
489 for (ego = ego_head; NULL != ego; ego = ego->next)
491 if (0 == strcmp (ego->identifier, identifier))
493 env = create_set_default_message (ego, name);
494 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
495 GNUNET_SERVICE_client_continue (client);
496 GNUNET_free (identifier);
501 GNUNET_free (identifier);
502 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to find ego `%s'\n", name);
504 send_result_code (client,
507 "default configured, but ego unknown (internal error)"));
508 GNUNET_SERVICE_client_continue (client);
513 * Compare the given two private keys for equality.
515 * @param pk1 one private key
516 * @param pk2 another private key
517 * @return 0 if the keys are equal
520 key_cmp (const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk1,
521 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk2)
523 return GNUNET_memcmp (pk1, pk2);
527 * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT message
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
534 check_set_default_message (void *cls, const struct SetDefaultMessage *msg)
540 size = ntohs (msg->header.size);
541 if (size <= sizeof (struct SetDefaultMessage))
544 return GNUNET_SYSERR;
546 name_len = ntohs (msg->name_len);
547 GNUNET_break (0 == ntohs (msg->reserved));
548 if (name_len + sizeof (struct SetDefaultMessage) != size)
551 return GNUNET_SYSERR;
553 str = (const char *) &msg[1];
554 if ('\0' != str[name_len - 1])
557 return GNUNET_SYSERR;
563 * Handler for SET_DEFAULT message from client, updates
564 * default identity for some service.
567 * @param client who sent the message
568 * @param message the message received
571 handle_set_default_message (void *cls, const struct SetDefaultMessage *sdm)
574 struct GNUNET_SERVICE_Client *client = cls;
577 str = GNUNET_strdup ((const char *) &sdm[1]);
578 GNUNET_STRINGS_utf8_tolower ((const char *) &sdm[1], str);
580 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
581 "Received SET_DEFAULT for service `%s' from client\n",
583 for (ego = ego_head; NULL != ego; ego = ego->next)
585 if (0 == key_cmp (ego->pk, &sdm->private_key))
587 GNUNET_CONFIGURATION_set_value_string (subsystem_cfg,
589 "DEFAULT_IDENTIFIER",
592 GNUNET_CONFIGURATION_write (subsystem_cfg, subsystem_cfg_file))
594 GNUNET_ERROR_TYPE_ERROR,
595 _ ("Failed to write subsystem default identifier map to `%s'.\n"),
597 send_result_code (client, 0, NULL);
598 GNUNET_SERVICE_client_continue (client);
603 send_result_code (client,
605 _ ("Unknown ego specified for service (internal error)"));
607 GNUNET_SERVICE_client_continue (client);
612 * Send an updated message for the given ego to all listeners.
614 * @param ego ego to send the update for
617 notify_listeners (struct Ego *ego)
619 struct UpdateMessage *um;
622 name_len = (NULL == ego->identifier) ? 0 : (strlen (ego->identifier) + 1);
623 um = GNUNET_malloc (sizeof (struct UpdateMessage) + name_len);
624 um->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE);
625 um->header.size = htons (sizeof (struct UpdateMessage) + name_len);
626 um->name_len = htons (name_len);
627 um->end_of_list = htons (GNUNET_NO);
628 um->private_key = *ego->pk;
629 GNUNET_memcpy (&um[1], ego->identifier, name_len);
630 GNUNET_notification_context_broadcast (nc, &um->header, GNUNET_NO);
635 * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_CREATE message
637 * @param cls client sending the message
638 * @param msg message of type `struct CreateRequestMessage`
639 * @return #GNUNET_OK if @a msg is well-formed
642 check_create_message (void *cls, const struct CreateRequestMessage *msg)
649 size = ntohs (msg->header.size);
650 if (size <= sizeof (struct CreateRequestMessage))
653 return GNUNET_SYSERR;
655 name_len = ntohs (msg->name_len);
656 GNUNET_break (0 == ntohs (msg->reserved));
657 if (name_len + sizeof (struct CreateRequestMessage) != size)
660 return GNUNET_SYSERR;
662 str = (const char *) &msg[1];
663 if ('\0' != str[name_len - 1])
666 return GNUNET_SYSERR;
672 * Handler for CREATE message from client, creates
676 * @param client who sent the message
677 * @param message the message received
680 handle_create_message (void *cls, const struct CreateRequestMessage *crm)
682 struct GNUNET_SERVICE_Client *client = cls;
687 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREATE message from client\n");
688 str = GNUNET_strdup ((const char *) &crm[1]);
689 GNUNET_STRINGS_utf8_tolower ((const char *) &crm[1], str);
690 for (ego = ego_head; NULL != ego; ego = ego->next)
692 if (0 == strcmp (ego->identifier, str))
694 send_result_code (client,
697 "identifier already in use for another ego"));
698 GNUNET_SERVICE_client_continue (client);
703 ego = GNUNET_new (struct Ego);
704 ego->pk = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
705 *ego->pk = crm->private_key;
706 ego->identifier = GNUNET_strdup (str);
707 GNUNET_CONTAINER_DLL_insert (ego_head, ego_tail, ego);
708 send_result_code (client, 0, NULL);
709 fn = get_ego_filename (ego);
710 (void) GNUNET_DISK_directory_create_for_file (fn);
711 if (sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey) !=
712 GNUNET_DISK_fn_write (fn,
714 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
715 GNUNET_DISK_PERM_USER_READ |
716 GNUNET_DISK_PERM_USER_WRITE))
717 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", fn);
720 notify_listeners (ego);
721 GNUNET_SERVICE_client_continue (client);
726 * Closure for 'handle_ego_rename'.
733 const char *old_name;
738 const char *new_name;
742 * An ego was renamed; rename it in all subsystems where it is
743 * currently set as the default.
745 * @param cls the 'struct RenameContext'
746 * @param section a section in the configuration to process
749 handle_ego_rename (void *cls, const char *section)
751 struct RenameContext *rc = cls;
754 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (subsystem_cfg,
756 "DEFAULT_IDENTIFIER",
759 if (0 != strcmp (id, rc->old_name))
764 GNUNET_CONFIGURATION_set_value_string (subsystem_cfg,
766 "DEFAULT_IDENTIFIER",
772 * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_RENAME message
774 * @param cls client sending the message
775 * @param msg message of type `struct RenameMessage`
776 * @return #GNUNET_OK if @a msg is well-formed
779 check_rename_message (void *cls, const struct RenameMessage *msg)
782 uint16_t old_name_len;
783 uint16_t new_name_len;
784 const char *old_name;
785 const char *new_name;
787 size = ntohs (msg->header.size);
788 if (size <= sizeof (struct RenameMessage))
791 return GNUNET_SYSERR;
793 old_name_len = ntohs (msg->old_name_len);
794 new_name_len = ntohs (msg->new_name_len);
795 old_name = (const char *) &msg[1];
796 new_name = &old_name[old_name_len];
797 if ((old_name_len + new_name_len + sizeof (struct RenameMessage) != size) ||
798 ('\0' != old_name[old_name_len - 1]) ||
799 ('\0' != new_name[new_name_len - 1]))
802 return GNUNET_SYSERR;
810 * Handler for RENAME message from client, creates
814 * @param client who sent the message
815 * @param message the message received
818 handle_rename_message (void *cls, const struct RenameMessage *rm)
820 uint16_t old_name_len;
824 struct RenameContext rename_ctx;
825 struct GNUNET_SERVICE_Client *client = cls;
828 const char *old_name_tmp;
830 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received RENAME message from client\n");
831 old_name_len = ntohs (rm->old_name_len);
832 old_name_tmp = (const char *) &rm[1];
833 old_name = GNUNET_strdup (old_name_tmp);
834 GNUNET_STRINGS_utf8_tolower (old_name_tmp, old_name);
835 new_name = GNUNET_strdup (&old_name_tmp[old_name_len]);
836 GNUNET_STRINGS_utf8_tolower (&old_name_tmp[old_name_len], new_name);
838 /* check if new name is already in use */
839 for (ego = ego_head; NULL != ego; ego = ego->next)
841 if (0 == strcmp (ego->identifier, new_name))
843 send_result_code (client, 1, gettext_noop ("target name already exists"));
844 GNUNET_SERVICE_client_continue (client);
845 GNUNET_free (old_name);
846 GNUNET_free (new_name);
851 /* locate old name and, if found, perform rename */
852 for (ego = ego_head; NULL != ego; ego = ego->next)
854 if (0 == strcmp (ego->identifier, old_name))
856 fn_old = get_ego_filename (ego);
857 GNUNET_free (ego->identifier);
858 rename_ctx.old_name = old_name;
859 rename_ctx.new_name = new_name;
860 GNUNET_CONFIGURATION_iterate_sections (subsystem_cfg,
864 GNUNET_CONFIGURATION_write (subsystem_cfg, subsystem_cfg_file))
866 GNUNET_ERROR_TYPE_ERROR,
867 _ ("Failed to write subsystem default identifier map to `%s'.\n"),
869 ego->identifier = GNUNET_strdup (new_name);
870 fn_new = get_ego_filename (ego);
871 if (0 != rename (fn_old, fn_new))
872 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "rename", fn_old);
873 GNUNET_free (fn_old);
874 GNUNET_free (fn_new);
875 GNUNET_free (old_name);
876 GNUNET_free (new_name);
877 notify_listeners (ego);
878 send_result_code (client, 0, NULL);
879 GNUNET_SERVICE_client_continue (client);
884 /* failed to locate old name */
885 send_result_code (client, 1, gettext_noop ("no matching ego found"));
886 GNUNET_free (old_name);
887 GNUNET_free (new_name);
888 GNUNET_SERVICE_client_continue (client);
893 * An ego was removed, remove it from all subsystems where it is
894 * currently set as the default.
896 * @param cls name of the removed ego (const char *)
897 * @param section a section in the configuration to process
900 handle_ego_delete (void *cls, const char *section)
902 const char *identifier = cls;
905 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (subsystem_cfg,
907 "DEFAULT_IDENTIFIER",
910 if (0 != strcmp (id, identifier))
915 GNUNET_CONFIGURATION_set_value_string (subsystem_cfg,
917 "DEFAULT_IDENTIFIER",
923 * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_DELETE message
925 * @param cls client sending the message
926 * @param msg message of type `struct DeleteMessage`
927 * @return #GNUNET_OK if @a msg is well-formed
930 check_delete_message (void *cls, const struct DeleteMessage *msg)
936 size = ntohs (msg->header.size);
937 if (size <= sizeof (struct DeleteMessage))
940 return GNUNET_SYSERR;
942 name = (const char *) &msg[1];
943 name_len = ntohs (msg->name_len);
944 if ((name_len + sizeof (struct DeleteMessage) != size) ||
945 (0 != ntohs (msg->reserved)) || ('\0' != name[name_len - 1]))
948 return GNUNET_SYSERR;
955 * Handler for DELETE message from client, creates
959 * @param client who sent the message
960 * @param message the message received
963 handle_delete_message (void *cls, const struct DeleteMessage *dm)
968 struct GNUNET_SERVICE_Client *client = cls;
970 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received DELETE message from client\n");
971 name = GNUNET_strdup ((const char *) &dm[1]);
972 GNUNET_STRINGS_utf8_tolower ((const char *) &dm[1], name);
974 for (ego = ego_head; NULL != ego; ego = ego->next)
976 if (0 == strcmp (ego->identifier, name))
978 GNUNET_CONTAINER_DLL_remove (ego_head, ego_tail, ego);
979 GNUNET_CONFIGURATION_iterate_sections (subsystem_cfg,
983 GNUNET_CONFIGURATION_write (subsystem_cfg, subsystem_cfg_file))
985 GNUNET_ERROR_TYPE_ERROR,
986 _ ("Failed to write subsystem default identifier map to `%s'.\n"),
988 fn = get_ego_filename (ego);
989 if (0 != unlink (fn))
990 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn);
992 GNUNET_free (ego->identifier);
993 ego->identifier = NULL;
994 notify_listeners (ego);
995 GNUNET_free (ego->pk);
998 send_result_code (client, 0, NULL);
999 GNUNET_SERVICE_client_continue (client);
1004 send_result_code (client, 1, gettext_noop ("no matching ego found"));
1006 GNUNET_SERVICE_client_continue (client);
1011 * Process the given file from the "EGODIR". Parses the file
1012 * and creates the respective 'struct Ego' in memory.
1015 * @param filename name of the file to parse
1016 * @return #GNUNET_OK to continue to iterate,
1017 * #GNUNET_NO to stop iteration with no error,
1018 * #GNUNET_SYSERR to abort iteration with error!
1021 process_ego_file (void *cls, const char *filename)
1026 fn = strrchr (filename, (int) DIR_SEPARATOR);
1032 ego = GNUNET_new (struct Ego);
1033 ego->pk = GNUNET_CRYPTO_ecdsa_key_create_from_file (filename);
1034 if (NULL == ego->pk)
1037 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1038 _ ("Failed to parse ego information in `%s'\n"),
1042 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded ego `%s'\n", fn + 1);
1043 ego->identifier = GNUNET_strdup (fn + 1);
1044 GNUNET_CONTAINER_DLL_insert (ego_head, ego_tail, ego);
1050 * Handle network size estimate clients.
1052 * @param cls closure
1053 * @param server the initialized server
1054 * @param c configuration to use
1058 const struct GNUNET_CONFIGURATION_Handle *c,
1059 struct GNUNET_SERVICE_Handle *service)
1062 nc = GNUNET_notification_context_create (1);
1063 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
1068 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "identity", "EGODIR");
1069 GNUNET_SCHEDULER_shutdown ();
1073 GNUNET_CONFIGURATION_get_value_filename (cfg,
1076 &subsystem_cfg_file))
1078 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1081 GNUNET_SCHEDULER_shutdown ();
1084 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1085 "Loading subsystem configuration `%s'\n",
1086 subsystem_cfg_file);
1087 subsystem_cfg = GNUNET_CONFIGURATION_create ();
1088 if ((GNUNET_YES == GNUNET_DISK_file_test (subsystem_cfg_file)) &&
1090 GNUNET_CONFIGURATION_parse (subsystem_cfg, subsystem_cfg_file)))
1092 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1094 "Failed to parse subsystem identity configuration file `%s'\n"),
1095 subsystem_cfg_file);
1096 GNUNET_SCHEDULER_shutdown ();
1099 stats = GNUNET_STATISTICS_create ("identity", cfg);
1100 if (GNUNET_OK != GNUNET_DISK_directory_create (ego_directory))
1102 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1103 _ ("Failed to create directory `%s' for storing egos\n"),
1106 GNUNET_DISK_directory_scan (ego_directory, &process_ego_file, NULL);
1107 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1112 * Define "main" method using service macro.
1114 GNUNET_SERVICE_MAIN (
1116 GNUNET_SERVICE_OPTION_NONE,
1119 &client_disconnect_cb,
1121 GNUNET_MQ_hd_fixed_size (start_message,
1122 GNUNET_MESSAGE_TYPE_IDENTITY_START,
1123 struct GNUNET_MessageHeader,
1125 GNUNET_MQ_hd_var_size (lookup_message,
1126 GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP,
1127 struct LookupMessage,
1129 GNUNET_MQ_hd_var_size (lookup_by_suffix_message,
1130 GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP_BY_SUFFIX,
1131 struct LookupMessage,
1133 GNUNET_MQ_hd_var_size (get_default_message,
1134 GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT,
1135 struct GetDefaultMessage,
1137 GNUNET_MQ_hd_var_size (set_default_message,
1138 GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT,
1139 struct SetDefaultMessage,
1141 GNUNET_MQ_hd_var_size (create_message,
1142 GNUNET_MESSAGE_TYPE_IDENTITY_CREATE,
1143 struct CreateRequestMessage,
1145 GNUNET_MQ_hd_var_size (rename_message,
1146 GNUNET_MESSAGE_TYPE_IDENTITY_RENAME,
1147 struct RenameMessage,
1149 GNUNET_MQ_hd_var_size (delete_message,
1150 GNUNET_MESSAGE_TYPE_IDENTITY_DELETE,
1151 struct DeleteMessage,
1153 GNUNET_MQ_handler_end ());
1156 /* end of gnunet-service-identity.c */