aboutsummaryrefslogtreecommitdiff
path: root/src/identity/gnunet-service-identity.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/identity/gnunet-service-identity.c')
-rw-r--r--src/identity/gnunet-service-identity.c1253
1 files changed, 0 insertions, 1253 deletions
diff --git a/src/identity/gnunet-service-identity.c b/src/identity/gnunet-service-identity.c
deleted file mode 100644
index 2bb4b0897..000000000
--- a/src/identity/gnunet-service-identity.c
+++ /dev/null
@@ -1,1253 +0,0 @@
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 */
45struct 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_IDENTITY_PrivateKey pk;
61
62 /**
63 * String identifier for the ego.
64 */
65 char *identifier;
66};
67
68
69/**
70 * Handle to our current configuration.
71 */
72static 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 */
78static struct GNUNET_CONFIGURATION_Handle *subsystem_cfg;
79
80/**
81 * Handle to the statistics service.
82 */
83static struct GNUNET_STATISTICS_Handle *stats;
84
85/**
86 * Notification context, simplifies client broadcasts.
87 */
88static struct GNUNET_NotificationContext *nc;
89
90/**
91 * Directory where we store the identities.
92 */
93static char *ego_directory;
94
95/**
96 * Configuration file name where subsystem information is kept.
97 */
98static char *subsystem_cfg_file;
99
100/**
101 * Head of DLL of all egos.
102 */
103static struct Ego *ego_head;
104
105/**
106 * Tail of DLL of all egos.
107 */
108static 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 */
117static char *
118get_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 */
138static void
139client_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 */
157static void *
158client_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 */
171static void
172shutdown_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 */
210static void
211send_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 */
242static struct GNUNET_MQ_Envelope *
243create_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 */
266static struct GNUNET_MQ_Envelope *
267create_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 */
295static void
296handle_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 */
336static int
337check_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 */
352static void
353handle_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 */
386static int
387check_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 */
402static void
403handle_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 */
448static int
449check_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 */
482static void
483handle_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 */
540static int
541key_cmp (const struct GNUNET_IDENTITY_PrivateKey *pk1,
542 const struct GNUNET_IDENTITY_PrivateKey *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 */
555static int
556check_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 */
594static void
595handle_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 */
642static void
643notify_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 */
668static int
669check_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 new identity.
701 *
702 * @param cls unused
703 * @param client who sent the message
704 * @param message the message received
705 */
706static void
707handle_create_message (void *cls,
708 const struct CreateRequestMessage *crm)
709{
710 struct GNUNET_SERVICE_Client *client = cls;
711 struct Ego *ego;
712 char *str;
713 char *fn;
714
715 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREATE message from client\n");
716 str = GNUNET_strdup ((const char *) &crm[1]);
717 GNUNET_STRINGS_utf8_tolower ((const char *) &crm[1], str);
718 for (ego = ego_head; NULL != ego; ego = ego->next)
719 {
720 if (0 == strcmp (ego->identifier, str))
721 {
722 send_result_code (client,
723 1,
724 gettext_noop (
725 "identifier already in use for another ego"));
726 GNUNET_SERVICE_client_continue (client);
727 GNUNET_free (str);
728 return;
729 }
730 }
731 ego = GNUNET_new (struct Ego);
732 ego->pk = crm->private_key;
733 ego->identifier = GNUNET_strdup (str);
734 GNUNET_CONTAINER_DLL_insert (ego_head,
735 ego_tail,
736 ego);
737 send_result_code (client, 0, NULL);
738 fn = get_ego_filename (ego);
739 if (GNUNET_OK !=
740 GNUNET_DISK_fn_write (fn,
741 &crm->private_key,
742 sizeof(struct GNUNET_IDENTITY_PrivateKey),
743 GNUNET_DISK_PERM_USER_READ
744 | GNUNET_DISK_PERM_USER_WRITE))
745 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", fn);
746 GNUNET_free (fn);
747 GNUNET_free (str);
748 notify_listeners (ego);
749 GNUNET_SERVICE_client_continue (client);
750}
751
752
753/**
754 * Closure for 'handle_ego_rename'.
755 */
756struct RenameContext
757{
758 /**
759 * Old name.
760 */
761 const char *old_name;
762
763 /**
764 * New name.
765 */
766 const char *new_name;
767};
768
769/**
770 * An ego was renamed; rename it in all subsystems where it is
771 * currently set as the default.
772 *
773 * @param cls the 'struct RenameContext'
774 * @param section a section in the configuration to process
775 */
776static void
777handle_ego_rename (void *cls, const char *section)
778{
779 struct RenameContext *rc = cls;
780 char *id;
781
782 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (subsystem_cfg,
783 section,
784 "DEFAULT_IDENTIFIER",
785 &id))
786 return;
787 if (0 != strcmp (id, rc->old_name))
788 {
789 GNUNET_free (id);
790 return;
791 }
792 GNUNET_CONFIGURATION_set_value_string (subsystem_cfg,
793 section,
794 "DEFAULT_IDENTIFIER",
795 rc->new_name);
796 GNUNET_free (id);
797}
798
799
800/**
801 * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_RENAME message
802 *
803 * @param cls client sending the message
804 * @param msg message of type `struct RenameMessage`
805 * @return #GNUNET_OK if @a msg is well-formed
806 */
807static int
808check_rename_message (void *cls, const struct RenameMessage *msg)
809{
810 uint16_t size;
811 uint16_t old_name_len;
812 uint16_t new_name_len;
813 const char *old_name;
814 const char *new_name;
815
816 size = ntohs (msg->header.size);
817 if (size <= sizeof(struct RenameMessage))
818 {
819 GNUNET_break (0);
820 return GNUNET_SYSERR;
821 }
822 old_name_len = ntohs (msg->old_name_len);
823 new_name_len = ntohs (msg->new_name_len);
824 old_name = (const char *) &msg[1];
825 new_name = &old_name[old_name_len];
826 if ((old_name_len + new_name_len + sizeof(struct RenameMessage) != size) ||
827 ('\0' != old_name[old_name_len - 1]) ||
828 ('\0' != new_name[new_name_len - 1]))
829 {
830 GNUNET_break (0);
831 return GNUNET_SYSERR;
832 }
833
834 return GNUNET_OK;
835}
836
837
838/**
839 * Handler for RENAME message from client, creates
840 * new identity.
841 *
842 * @param cls unused
843 * @param client who sent the message
844 * @param message the message received
845 */
846static void
847handle_rename_message (void *cls, const struct RenameMessage *rm)
848{
849 uint16_t old_name_len;
850 struct Ego *ego;
851 char *old_name;
852 char *new_name;
853 struct RenameContext rename_ctx;
854 struct GNUNET_SERVICE_Client *client = cls;
855 char *fn_old;
856 char *fn_new;
857 const char *old_name_tmp;
858
859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received RENAME message from client\n");
860 old_name_len = ntohs (rm->old_name_len);
861 old_name_tmp = (const char *) &rm[1];
862 old_name = GNUNET_strdup (old_name_tmp);
863 GNUNET_STRINGS_utf8_tolower (old_name_tmp, old_name);
864 new_name = GNUNET_strdup (&old_name_tmp[old_name_len]);
865 GNUNET_STRINGS_utf8_tolower (&old_name_tmp[old_name_len], new_name);
866
867 /* check if new name is already in use */
868 for (ego = ego_head; NULL != ego; ego = ego->next)
869 {
870 if (0 == strcmp (ego->identifier, new_name))
871 {
872 send_result_code (client, 1, gettext_noop ("target name already exists"));
873 GNUNET_SERVICE_client_continue (client);
874 GNUNET_free (old_name);
875 GNUNET_free (new_name);
876 return;
877 }
878 }
879
880 /* locate old name and, if found, perform rename */
881 for (ego = ego_head; NULL != ego; ego = ego->next)
882 {
883 if (0 == strcmp (ego->identifier, old_name))
884 {
885 fn_old = get_ego_filename (ego);
886 GNUNET_free (ego->identifier);
887 rename_ctx.old_name = old_name;
888 rename_ctx.new_name = new_name;
889 GNUNET_CONFIGURATION_iterate_sections (subsystem_cfg,
890 &handle_ego_rename,
891 &rename_ctx);
892 if (GNUNET_OK !=
893 GNUNET_CONFIGURATION_write (subsystem_cfg, subsystem_cfg_file))
894 GNUNET_log (
895 GNUNET_ERROR_TYPE_ERROR,
896 _ ("Failed to write subsystem default identifier map to `%s'.\n"),
897 subsystem_cfg_file);
898 ego->identifier = GNUNET_strdup (new_name);
899 fn_new = get_ego_filename (ego);
900 if (0 != rename (fn_old, fn_new))
901 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "rename", fn_old);
902 GNUNET_free (fn_old);
903 GNUNET_free (fn_new);
904 GNUNET_free (old_name);
905 GNUNET_free (new_name);
906 notify_listeners (ego);
907 send_result_code (client, 0, NULL);
908 GNUNET_SERVICE_client_continue (client);
909 return;
910 }
911 }
912
913 /* failed to locate old name */
914 send_result_code (client, 1, gettext_noop ("no matching ego found"));
915 GNUNET_free (old_name);
916 GNUNET_free (new_name);
917 GNUNET_SERVICE_client_continue (client);
918}
919
920
921/**
922 * An ego was removed, remove it from all subsystems where it is
923 * currently set as the default.
924 *
925 * @param cls name of the removed ego (const char *)
926 * @param section a section in the configuration to process
927 */
928static void
929handle_ego_delete (void *cls, const char *section)
930{
931 const char *identifier = cls;
932 char *id;
933
934 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (subsystem_cfg,
935 section,
936 "DEFAULT_IDENTIFIER",
937 &id))
938 return;
939 if (0 != strcmp (id, identifier))
940 {
941 GNUNET_free (id);
942 return;
943 }
944 GNUNET_CONFIGURATION_set_value_string (subsystem_cfg,
945 section,
946 "DEFAULT_IDENTIFIER",
947 NULL);
948 GNUNET_free (id);
949}
950
951
952/**
953 * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_DELETE message
954 *
955 * @param cls client sending the message
956 * @param msg message of type `struct DeleteMessage`
957 * @return #GNUNET_OK if @a msg is well-formed
958 */
959static int
960check_delete_message (void *cls, const struct DeleteMessage *msg)
961{
962 uint16_t size;
963 uint16_t name_len;
964 const char *name;
965
966 size = ntohs (msg->header.size);
967 if (size <= sizeof(struct DeleteMessage))
968 {
969 GNUNET_break (0);
970 return GNUNET_SYSERR;
971 }
972 name = (const char *) &msg[1];
973 name_len = ntohs (msg->name_len);
974 if ((name_len + sizeof(struct DeleteMessage) != size) ||
975 (0 != ntohs (msg->reserved)) || ('\0' != name[name_len - 1]))
976 {
977 GNUNET_break (0);
978 return GNUNET_SYSERR;
979 }
980 return GNUNET_OK;
981}
982
983
984/**
985 * Handler for DELETE message from client, creates
986 * new identity.
987 *
988 * @param cls unused
989 * @param client who sent the message
990 * @param message the message received
991 */
992static void
993handle_delete_message (void *cls, const struct DeleteMessage *dm)
994{
995 struct Ego *ego;
996 char *name;
997 char *fn;
998 struct GNUNET_SERVICE_Client *client = cls;
999
1000 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received DELETE message from client\n");
1001 name = GNUNET_strdup ((const char *) &dm[1]);
1002 GNUNET_STRINGS_utf8_tolower ((const char *) &dm[1], name);
1003
1004 for (ego = ego_head; NULL != ego; ego = ego->next)
1005 {
1006 if (0 == strcmp (ego->identifier, name))
1007 {
1008 GNUNET_CONTAINER_DLL_remove (ego_head, ego_tail, ego);
1009 GNUNET_CONFIGURATION_iterate_sections (subsystem_cfg,
1010 &handle_ego_delete,
1011 ego->identifier);
1012 if (GNUNET_OK !=
1013 GNUNET_CONFIGURATION_write (subsystem_cfg, subsystem_cfg_file))
1014 GNUNET_log (
1015 GNUNET_ERROR_TYPE_ERROR,
1016 _ ("Failed to write subsystem default identifier map to `%s'.\n"),
1017 subsystem_cfg_file);
1018 fn = get_ego_filename (ego);
1019 if (0 != unlink (fn))
1020 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn);
1021 GNUNET_free (fn);
1022 GNUNET_free (ego->identifier);
1023 ego->identifier = NULL;
1024 notify_listeners (ego);
1025 GNUNET_free (ego);
1026 GNUNET_free (name);
1027 send_result_code (client, 0, NULL);
1028 GNUNET_SERVICE_client_continue (client);
1029 return;
1030 }
1031 }
1032
1033 send_result_code (client, 1, gettext_noop ("no matching ego found"));
1034 GNUNET_free (name);
1035 GNUNET_SERVICE_client_continue (client);
1036}
1037
1038
1039static int
1040read_from_file (const char *filename,
1041 void *buf,
1042 size_t buf_size)
1043{
1044 int fd;
1045 struct stat sb;
1046
1047 fd = open (filename,
1048 O_RDONLY);
1049 if (-1 == fd)
1050 {
1051 memset (buf,
1052 0,
1053 buf_size);
1054 return GNUNET_SYSERR;
1055 }
1056 if (0 != fstat (fd,
1057 &sb))
1058 {
1059 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1060 "stat",
1061 filename);
1062 GNUNET_assert (0 == close (fd));
1063 memset (buf,
1064 0,
1065 buf_size);
1066 return GNUNET_SYSERR;
1067 }
1068 if (sb.st_size != buf_size)
1069 {
1070 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1071 "File `%s' has wrong size (%llu), expected %llu bytes\n",
1072 filename,
1073 (unsigned long long) sb.st_size,
1074 (unsigned long long) buf_size);
1075 GNUNET_assert (0 == close (fd));
1076 memset (buf,
1077 0,
1078 buf_size);
1079 return GNUNET_SYSERR;
1080 }
1081 if (buf_size !=
1082 read (fd,
1083 buf,
1084 buf_size))
1085 {
1086 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1087 "read",
1088 filename);
1089 GNUNET_assert (0 == close (fd));
1090 memset (buf,
1091 0,
1092 buf_size);
1093 return GNUNET_SYSERR;
1094 }
1095 GNUNET_assert (0 == close (fd));
1096 return GNUNET_OK;
1097}
1098
1099
1100/**
1101 * Process the given file from the "EGODIR". Parses the file
1102 * and creates the respective 'struct Ego' in memory.
1103 *
1104 * @param cls NULL
1105 * @param filename name of the file to parse
1106 * @return #GNUNET_OK to continue to iterate,
1107 * #GNUNET_NO to stop iteration with no error,
1108 * #GNUNET_SYSERR to abort iteration with error!
1109 */
1110static int
1111process_ego_file (void *cls,
1112 const char *filename)
1113{
1114 struct Ego *ego;
1115 const char *fn;
1116
1117 fn = strrchr (filename, (int) DIR_SEPARATOR);
1118 if (NULL == fn)
1119 {
1120 GNUNET_break (0);
1121 return GNUNET_OK;
1122 }
1123 ego = GNUNET_new (struct Ego);
1124 if (GNUNET_OK !=
1125 read_from_file (filename,
1126 &ego->pk,
1127 sizeof (ego->pk)))
1128 {
1129 GNUNET_free (ego);
1130 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1131 _ ("Failed to parse ego information in `%s'\n"),
1132 filename);
1133 return GNUNET_OK;
1134 }
1135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1136 "Loaded ego `%s'\n",
1137 fn + 1);
1138 ego->identifier = GNUNET_strdup (fn + 1);
1139 GNUNET_CONTAINER_DLL_insert (ego_head, ego_tail, ego);
1140 return GNUNET_OK;
1141}
1142
1143
1144/**
1145 * Handle network size estimate clients.
1146 *
1147 * @param cls closure
1148 * @param server the initialized server
1149 * @param c configuration to use
1150 */
1151static void
1152run (void *cls,
1153 const struct GNUNET_CONFIGURATION_Handle *c,
1154 struct GNUNET_SERVICE_Handle *service)
1155{
1156 cfg = c;
1157 nc = GNUNET_notification_context_create (1);
1158 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
1159 "identity",
1160 "EGODIR",
1161 &ego_directory))
1162 {
1163 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "identity", "EGODIR");
1164 GNUNET_SCHEDULER_shutdown ();
1165 return;
1166 }
1167 if (GNUNET_OK !=
1168 GNUNET_CONFIGURATION_get_value_filename (cfg,
1169 "identity",
1170 "SUBSYSTEM_CFG",
1171 &subsystem_cfg_file))
1172 {
1173 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1174 "identity",
1175 "SUBSYSTEM_CFG");
1176 GNUNET_SCHEDULER_shutdown ();
1177 return;
1178 }
1179 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1180 "Loading subsystem configuration `%s'\n",
1181 subsystem_cfg_file);
1182 subsystem_cfg = GNUNET_CONFIGURATION_create ();
1183 if ((GNUNET_YES == GNUNET_DISK_file_test (subsystem_cfg_file)) &&
1184 (GNUNET_OK !=
1185 GNUNET_CONFIGURATION_parse (subsystem_cfg, subsystem_cfg_file)))
1186 {
1187 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1188 _ (
1189 "Failed to parse subsystem identity configuration file `%s'\n"),
1190 subsystem_cfg_file);
1191 GNUNET_SCHEDULER_shutdown ();
1192 return;
1193 }
1194 stats = GNUNET_STATISTICS_create ("identity", cfg);
1195 if (GNUNET_OK != GNUNET_DISK_directory_create (ego_directory))
1196 {
1197 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1198 _ ("Failed to create directory `%s' for storing egos\n"),
1199 ego_directory);
1200 }
1201 GNUNET_DISK_directory_scan (ego_directory,
1202 &process_ego_file,
1203 NULL);
1204 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1205}
1206
1207
1208/**
1209 * Define "main" method using service macro.
1210 */
1211GNUNET_SERVICE_MAIN (
1212 "identity",
1213 GNUNET_SERVICE_OPTION_NONE,
1214 &run,
1215 &client_connect_cb,
1216 &client_disconnect_cb,
1217 NULL,
1218 GNUNET_MQ_hd_fixed_size (start_message,
1219 GNUNET_MESSAGE_TYPE_IDENTITY_START,
1220 struct GNUNET_MessageHeader,
1221 NULL),
1222 GNUNET_MQ_hd_var_size (lookup_message,
1223 GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP,
1224 struct LookupMessage,
1225 NULL),
1226 GNUNET_MQ_hd_var_size (lookup_by_suffix_message,
1227 GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP_BY_SUFFIX,
1228 struct LookupMessage,
1229 NULL),
1230 GNUNET_MQ_hd_var_size (get_default_message,
1231 GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT,
1232 struct GetDefaultMessage,
1233 NULL),
1234 GNUNET_MQ_hd_var_size (set_default_message,
1235 GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT,
1236 struct SetDefaultMessage,
1237 NULL),
1238 GNUNET_MQ_hd_var_size (create_message,
1239 GNUNET_MESSAGE_TYPE_IDENTITY_CREATE,
1240 struct CreateRequestMessage,
1241 NULL),
1242 GNUNET_MQ_hd_var_size (rename_message,
1243 GNUNET_MESSAGE_TYPE_IDENTITY_RENAME,
1244 struct RenameMessage,
1245 NULL),
1246 GNUNET_MQ_hd_var_size (delete_message,
1247 GNUNET_MESSAGE_TYPE_IDENTITY_DELETE,
1248 struct DeleteMessage,
1249 NULL),
1250 GNUNET_MQ_handler_end ());
1251
1252
1253/* end of gnunet-service-identity.c */