9be5e069808d145e9b525f9a7d4194e3448d4bc7
[oweals/gnunet.git] / src / identity / gnunet-service-identity.c
1 /*
2   This file is part of GNUnet.
3   (C) 2013 Christian Grothoff (and other contributing authors)
4
5   GNUnet is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published
7   by the Free Software Foundation; either version 3, or (at your
8   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   General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with GNUnet; see the file COPYING.  If not, write to the
17   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18   Boston, MA 02111-1307, USA.
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 #include "platform.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_protocols.h"
33 #include "gnunet_statistics_service.h"
34 #include "gnunet_identity_service.h"
35 #include "identity.h"
36
37
38 /**
39  * Information we keep about each ego.
40  */
41 struct Ego
42 {
43
44   /**
45    * We keep egos in a DLL.
46    */ 
47   struct Ego *next;
48
49   /**
50    * We keep egos in a DLL.
51    */ 
52   struct Ego *prev;
53
54   /**
55    * Private key of the ego.
56    */
57   struct GNUNET_CRYPTO_EccPrivateKey *pk;
58
59   /**
60    * String identifier for the ego.
61    */
62   char *identifier;
63
64 };
65
66
67 /**
68  * Handle to our current configuration.
69  */
70 static const struct GNUNET_CONFIGURATION_Handle *cfg;
71
72 /**
73  * Handle to subsystem configuration which for each subsystem contains
74  * the name of the default ego.
75  */
76 static struct GNUNET_CONFIGURATION_Handle *subsystem_cfg;
77
78 /**
79  * Handle to the statistics service.
80  */
81 static struct GNUNET_STATISTICS_Handle *stats;
82
83 /**
84  * Notification context, simplifies client broadcasts.
85  */
86 static struct GNUNET_SERVER_NotificationContext *nc;
87
88 /**
89  * Directory where we store the identities.
90  */
91 static char *ego_directory;
92
93 /**
94  * Configuration file name where subsystem information is kept.
95  */
96 static char *subsystem_cfg_file;
97
98 /**
99  * Head of DLL of all egos.
100  */
101 static struct Ego *ego_head;
102
103 /**
104  * Tail of DLL of all egos.
105  */
106 static struct Ego *ego_tail;
107
108
109 /**
110  * Task run during shutdown.
111  *
112  * @param cls unused
113  * @param tc unused
114  */
115 static void
116 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
117 {
118   struct Ego *e;
119
120   if (NULL != nc)
121   {
122     GNUNET_SERVER_notification_context_destroy (nc);
123     nc = NULL;
124   }
125   if (NULL != stats)
126   {
127     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
128     stats = NULL;
129   }
130   GNUNET_CONFIGURATION_destroy (subsystem_cfg);
131   subsystem_cfg = NULL;
132   GNUNET_free (subsystem_cfg_file);
133   subsystem_cfg_file = NULL;
134   GNUNET_free (ego_directory);
135   ego_directory = NULL;
136   while (NULL != (e = ego_head))
137   {
138     GNUNET_CONTAINER_DLL_remove (ego_head, ego_tail, e);
139     GNUNET_CRYPTO_ecc_key_free (e->pk);
140     GNUNET_free (e);
141   }
142 }
143
144
145 /**
146  * Send a result code back to the client.
147  *
148  * @param client client that should receive the result code
149  * @param result_code code to transmit
150  * @param emsg error message to include (or NULL for none)
151  */
152 static void
153 send_result_code (struct GNUNET_SERVER_Client *client,
154                   uint32_t result_code,
155                   const char *emsg)
156 {
157   struct GNUNET_IDENTITY_ResultCodeMessage *rcm;
158   size_t elen;
159
160   if (NULL == emsg)
161     elen = 0;
162   else
163     elen = strlen (emsg) + 1;
164   rcm = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ResultCodeMessage) + elen);
165   rcm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE);
166   rcm->header.size = htons (sizeof (struct GNUNET_IDENTITY_ResultCodeMessage) + elen);
167   rcm->result_code = htonl (result_code);
168   memcpy (&rcm[1], emsg, elen);
169   GNUNET_SERVER_notification_context_unicast (nc, client, &rcm->header, GNUNET_YES);  
170   GNUNET_free (rcm);
171 }
172
173
174 /**
175  * Create an update message with information about the current state of an ego.
176  *
177  * @param ego ego to create message for
178  * @return corresponding update message
179  */
180 static struct GNUNET_IDENTITY_UpdateMessage *
181 create_update_message (struct Ego *ego)
182 {
183   struct GNUNET_IDENTITY_UpdateMessage *um;
184   char *str;
185   uint16_t pk_len;
186   size_t name_len;
187   struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *enc;
188
189   name_len = (NULL == ego->identifier) ? 0 : (strlen (ego->identifier) + 1);
190   enc = GNUNET_CRYPTO_ecc_encode_key (ego->pk);
191   pk_len = ntohs (enc->size);
192   um = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_UpdateMessage) + pk_len + name_len);
193   um->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE);
194   um->header.size = htons (sizeof (struct GNUNET_IDENTITY_UpdateMessage) + pk_len + name_len);
195   um->name_len = htons (name_len);
196   um->pk_len = htons (pk_len);
197   str = (char *) &um[1];
198   memcpy (str, enc, pk_len);
199   memcpy (&str[pk_len], ego->identifier, name_len);
200   GNUNET_free (enc);
201   return um;
202 }
203
204
205 /**
206  * Handler for START message from client, sends information
207  * about all identities to the client immediately and 
208  * adds the client to the notification context for future
209  * updates.
210  *
211  * @param cls unused
212  * @param client who sent the message
213  * @param message the message received
214  */
215 static void
216 handle_start_message (void *cls, struct GNUNET_SERVER_Client *client,
217                       const struct GNUNET_MessageHeader *message)
218 {
219   struct GNUNET_IDENTITY_UpdateMessage *um;
220   struct Ego *ego;
221
222   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
223               "Received START message from client\n");
224   GNUNET_SERVER_notification_context_add (nc, client);
225   for (ego = ego_head; NULL != ego; ego = ego->next)
226   {
227     um = create_update_message (ego);
228     GNUNET_SERVER_notification_context_unicast (nc, client, &um->header, GNUNET_YES);
229     GNUNET_free (um);
230   }
231   GNUNET_SERVER_receive_done (client, GNUNET_OK);
232 }
233
234
235 /**
236  * Handler for GET_DEFAULT message from client, returns
237  * default identity for some service.
238  *
239  * @param cls unused
240  * @param client who sent the message
241  * @param message the message received
242  */
243 static void
244 handle_get_default_message (void *cls, struct GNUNET_SERVER_Client *client,
245                             const struct GNUNET_MessageHeader *message)
246 {
247   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
248               "Received GET_DEFAULT message from client\n");
249   // setup_estimate_message (&em);
250   // GNUNET_SERVER_notification_context_unicast (nc, client, &em.header, GNUNET_YES);
251   GNUNET_break (0); // not implemented!
252   GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
253 }
254
255
256 /**
257  * Handler for SET_DEFAULT message from client, updates
258  * default identity for some service.
259  *
260  * @param cls unused
261  * @param client who sent the message
262  * @param message the message received
263  */
264 static void
265 handle_set_default_message (void *cls, struct GNUNET_SERVER_Client *client,
266                             const struct GNUNET_MessageHeader *message)
267 {
268   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
269               "Received SET_DEFAULT message from client\n");
270   // setup_estimate_message (&em);
271   // GNUNET_SERVER_notification_context_unicast (nc, client, &em.header, GNUNET_YES);
272   GNUNET_break (0); // not implemented!
273   GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
274 }
275
276
277 /**
278  * Handler for CREATE message from client, creates
279  * new identity.
280  *
281  * @param cls unused
282  * @param client who sent the message
283  * @param message the message received
284  */
285 static void
286 handle_create_message (void *cls, struct GNUNET_SERVER_Client *client,
287                        const struct GNUNET_MessageHeader *message)
288 {
289   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
290               "Received CREATE message from client\n");
291   // setup_estimate_message (&em);
292   // GNUNET_SERVER_notification_context_unicast (nc, client, &em.header, GNUNET_YES);
293   GNUNET_break (0); // not implemented!
294   GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
295 }
296
297
298
299 /**
300  * Handler for RENAME message from client, creates
301  * new identity.
302  *
303  * @param cls unused
304  * @param client who sent the message
305  * @param message the message received
306  */
307 static void
308 handle_rename_message (void *cls, struct GNUNET_SERVER_Client *client,
309                        const struct GNUNET_MessageHeader *message)
310 {
311   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
312               "Received RENAME message from client\n");
313   // setup_estimate_message (&em);
314   // GNUNET_SERVER_notification_context_unicast (nc, client, &em.header, GNUNET_YES);
315   GNUNET_break (0); // not implemented!
316   GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
317 }
318
319
320 /**
321  * Handler for DELETE message from client, creates
322  * new identity.
323  *
324  * @param cls unused
325  * @param client who sent the message
326  * @param message the message received
327  */
328 static void
329 handle_delete_message (void *cls, struct GNUNET_SERVER_Client *client,
330                        const struct GNUNET_MessageHeader *message)
331 {
332   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
333               "Received DELETE message from client\n");
334   // setup_estimate_message (&em);
335   // GNUNET_SERVER_notification_context_unicast (nc, client, &em.header, GNUNET_YES);
336   GNUNET_break (0); // not implemented!
337
338   send_result_code (client, 1, gettext_noop ("no matching ego found"));
339   GNUNET_SERVER_receive_done (client, GNUNET_OK);
340 }
341
342
343 /**
344  * Handle network size estimate clients.
345  *
346  * @param cls closure
347  * @param server the initialized server
348  * @param c configuration to use
349  */
350 static void
351 run (void *cls, 
352      struct GNUNET_SERVER_Handle *server,
353      const struct GNUNET_CONFIGURATION_Handle *c)
354 {
355   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
356     {&handle_start_message, NULL,
357      GNUNET_MESSAGE_TYPE_IDENTITY_START, sizeof (struct GNUNET_MessageHeader)},
358     {&handle_get_default_message, NULL,
359      GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT, 0},
360     {&handle_set_default_message, NULL,
361      GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT, 0},
362     {&handle_create_message, NULL,
363      GNUNET_MESSAGE_TYPE_IDENTITY_CREATE, 0},
364     {&handle_rename_message, NULL,
365      GNUNET_MESSAGE_TYPE_IDENTITY_RENAME, 0},
366     {&handle_delete_message, NULL,
367      GNUNET_MESSAGE_TYPE_IDENTITY_DELETE, 0},
368     {NULL, NULL, 0, 0}
369   };
370
371   cfg = c;
372   if (GNUNET_OK !=
373       GNUNET_CONFIGURATION_get_value_filename (cfg, "identity",
374                                                "EGODIR",
375                                                &ego_directory))
376   {
377     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "identity", "EGODIR");
378     GNUNET_SCHEDULER_shutdown ();
379     return;
380   }
381   if (GNUNET_OK !=
382       GNUNET_CONFIGURATION_get_value_filename (cfg, "identity",
383                                                "SUBSYSTEM_CFG",
384                                                &subsystem_cfg_file))
385   {
386     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "identity", "SUBSYSTEM_CFG");
387     GNUNET_SCHEDULER_shutdown ();
388     return;
389   }
390   subsystem_cfg = GNUNET_CONFIGURATION_create ();
391   if ( (GNUNET_YES ==
392         GNUNET_DISK_file_test (subsystem_cfg_file)) &&
393        (GNUNET_OK != 
394         GNUNET_CONFIGURATION_parse (subsystem_cfg,
395                                     subsystem_cfg_file)) )
396   {
397     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
398                 _("Failed to parse subsystem identity configuration file `%s'\n"),
399                 subsystem_cfg_file);
400     GNUNET_SCHEDULER_shutdown ();
401     return;
402   }
403   stats = GNUNET_STATISTICS_create ("identity", cfg);
404   GNUNET_SERVER_add_handlers (server, handlers);
405   nc = GNUNET_SERVER_notification_context_create (server, 1);
406   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
407                                 NULL);
408 }
409
410
411 /**
412  * The main function for the network size estimation service.
413  *
414  * @param argc number of arguments from the command line
415  * @param argv command line arguments
416  * @return 0 ok, 1 on error
417  */
418 int
419 main (int argc, char *const *argv)
420 {
421   return (GNUNET_OK ==
422           GNUNET_SERVICE_run (argc, argv, "identity", 
423                               GNUNET_SERVICE_OPTION_NONE,
424                               &run, NULL)) ? 0 : 1;
425 }
426
427
428 /* end of gnunet-service-identity.c */