- fixes
[oweals/gnunet.git] / src / namestore / gnunet-service-namestore.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 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 namestore/gnunet-service-namestore.c
23  * @brief namestore for the GNUnet naming system
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_getopt_lib.h"
28 #include "gnunet_service_lib.h"
29 #include "gnunet_namestore_service.h"
30 #include "gnunet_namestore_plugin.h"
31 #include "gnunet_signatures.h"
32 #include "namestore.h"
33
34
35
36 /**
37  * A namestore operation.
38  */
39 struct GNUNET_NAMESTORE_ZoneIteration
40 {
41   struct GNUNET_NAMESTORE_ZoneIteration *next;
42   struct GNUNET_NAMESTORE_ZoneIteration *prev;
43
44   struct GNUNET_NAMESTORE_Client * client;
45
46   GNUNET_HashCode zone;
47
48   uint64_t request_id;
49   uint32_t offset;
50
51 };
52
53
54 /**
55  * A namestore client
56  */
57 struct GNUNET_NAMESTORE_Client
58 {
59   struct GNUNET_NAMESTORE_Client *next;
60   struct GNUNET_NAMESTORE_Client *prev;
61
62   struct GNUNET_SERVER_Client * client;
63
64   struct GNUNET_NAMESTORE_ZoneIteration *op_head;
65   struct GNUNET_NAMESTORE_ZoneIteration *op_tail;
66 };
67
68
69
70 /**
71  * Configuration handle.
72  */
73 const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
74
75 static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
76
77 /**
78  * Our notification context.
79  */
80 static struct GNUNET_SERVER_NotificationContext *snc;
81
82 static char *db_lib_name;
83
84 static struct GNUNET_NAMESTORE_Client *client_head;
85 static struct GNUNET_NAMESTORE_Client *client_tail;
86
87
88 /**
89  * Task run during shutdown.
90  *
91  * @param cls unused
92  * @param tc unused
93  */
94 static void
95 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
96 {
97   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
98
99   struct GNUNET_NAMESTORE_ZoneIteration * no;
100   struct GNUNET_NAMESTORE_ZoneIteration * tmp;
101   struct GNUNET_NAMESTORE_Client * nc;
102   struct GNUNET_NAMESTORE_Client * next;
103
104   GNUNET_SERVER_notification_context_destroy (snc);
105   snc = NULL;
106
107   for (nc = client_head; nc != NULL; nc = next)
108   {
109     next = nc->next;
110     for (no = nc->op_head; no != NULL; no = tmp)
111     {
112       GNUNET_break (0);
113       GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
114       tmp = no->next;
115       GNUNET_free (no);
116     }
117     GNUNET_SERVER_client_drop(nc->client);
118     GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
119     GNUNET_free (nc);
120   }
121
122   GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
123   GNUNET_free (db_lib_name);
124 }
125
126 static struct GNUNET_NAMESTORE_Client *
127 client_lookup (struct GNUNET_SERVER_Client *client)
128 {
129   struct GNUNET_NAMESTORE_Client * nc;
130
131   GNUNET_assert (NULL != client);
132
133   for (nc = client_head; nc != NULL; nc = nc->next)
134   {
135     if (client == nc->client)
136       break;
137   }
138   return nc;
139 }
140
141
142 /**
143  * Called whenever a client is disconnected.  Frees our
144  * resources associated with that client.
145  *
146  * @param cls closure
147  * @param client identification of the client
148  */
149 static void
150 client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
151 {
152   struct GNUNET_NAMESTORE_ZoneIteration * no;
153   struct GNUNET_NAMESTORE_Client * nc;
154   if (NULL == client)
155     return;
156
157   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected \n", client);
158
159   nc = client_lookup (client);
160
161   if ((NULL == client) || (NULL == nc))
162     return;
163
164   for (no = nc->op_head; no != NULL; no = no->next)
165   {
166     GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
167     GNUNET_free (no);
168   }
169
170   GNUNET_SERVER_client_drop(nc->client);
171   GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
172   GNUNET_free (nc);
173 }
174
175 static void handle_start (void *cls,
176                           struct GNUNET_SERVER_Client * client,
177                           const struct GNUNET_MessageHeader * message)
178 {
179   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
180
181   struct GNUNET_NAMESTORE_Client * nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
182   nc->client = client;
183   GNUNET_SERVER_notification_context_add (snc, client);
184   GNUNET_CONTAINER_DLL_insert(client_head, client_tail, nc);
185   GNUNET_SERVER_client_keep (client);
186   GNUNET_SERVER_receive_done (client, GNUNET_OK);
187 }
188
189 struct LookupNameContext
190 {
191   struct GNUNET_NAMESTORE_Client *nc;
192   uint32_t request_id;
193   uint32_t record_type;
194   GNUNET_HashCode *zone;
195   char * name;
196 };
197
198
199
200
201 static void
202 handle_lookup_name_it (void *cls,
203     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
204     struct GNUNET_TIME_Absolute expire,
205     const char *name,
206     unsigned int rd_count,
207     const struct GNUNET_NAMESTORE_RecordData *rd,
208     const struct GNUNET_CRYPTO_RsaSignature *signature)
209 {
210   /* send response */
211   struct LookupNameContext *lnc = cls;
212   struct LookupNameResponseMessage *lnr_msg;
213
214   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key_tmp;
215   struct GNUNET_NAMESTORE_RecordData *rd_selected = NULL;
216   char *rd_tmp;
217   char *name_tmp;
218   size_t rd_ser_len;
219   struct GNUNET_CRYPTO_RsaSignature *signature_tmp;
220
221
222
223   size_t r_size = 0;
224
225   size_t name_len = 0;
226   if (NULL != name)
227     name_len = strlen(name) + 1;
228
229   int copied_elements = 0;
230   int contains_signature = 0;
231   int c;
232
233   /* count records to copy */
234   if (rd_count != 0)
235   {
236     if (lnc->record_type != 0)
237     {
238       /* special record type needed */
239       for (c = 0; c < rd_count; c ++)
240         if (rd[c].record_type == lnc->record_type)
241           copied_elements++; /* found matching record */
242       rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
243       copied_elements = 0;
244       for (c = 0; c < rd_count; c ++)
245       {
246         if (rd[c].record_type == lnc->record_type)
247         {
248           /* found matching record */
249           memcpy (&rd_selected[copied_elements], &rd[c], sizeof (struct GNUNET_NAMESTORE_RecordData));
250           copied_elements++;
251         }
252       }
253     }
254     else
255     {
256       copied_elements = rd_count;
257       rd_selected = (struct GNUNET_NAMESTORE_RecordData *) rd;
258     }
259   }
260   else
261   {
262     /* No results */
263     copied_elements = 0;
264     rd_selected = NULL;
265     expire = GNUNET_TIME_UNIT_ZERO_ABS;
266   }
267
268
269
270   rd_ser_len = GNUNET_NAMESTORE_records_get_size(copied_elements, rd_selected);
271   char rd_ser[rd_ser_len];
272   GNUNET_NAMESTORE_records_serialize(copied_elements, rd_selected, rd_ser_len, rd_ser);
273
274   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records for name `%s' in zone `%s'\n",
275       copied_elements, lnc->name, GNUNET_h2s(lnc->zone));
276
277   if ((copied_elements == rd_count) && (signature != NULL))
278       contains_signature = GNUNET_YES;
279
280   if (rd_selected != rd)
281     GNUNET_free (rd_selected);
282
283   r_size = sizeof (struct LookupNameResponseMessage) +
284            sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
285            name_len +
286            rd_ser_len +
287            contains_signature * sizeof (struct GNUNET_CRYPTO_RsaSignature);
288
289   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "NAMESTORE_LOOKUP_NAME_RESPONSE");
290
291   lnr_msg = GNUNET_malloc (r_size);
292
293   lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
294   lnr_msg->gns_header.header.size = ntohs (r_size);
295   lnr_msg->gns_header.r_id = htonl (lnc->request_id);
296   lnr_msg->rd_count = htons (rd_count);
297   lnr_msg->rd_len = htons (rd_ser_len);
298   lnr_msg->name_len = htons (name_len);
299   lnr_msg->expire = GNUNET_TIME_absolute_hton(expire);
300   lnr_msg->contains_sig = htons (contains_signature);
301
302   zone_key_tmp =  (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &lnr_msg[1];
303   name_tmp = (char *) &zone_key_tmp[1];
304   rd_tmp = &name_tmp[name_len];
305   signature_tmp = (struct GNUNET_CRYPTO_RsaSignature *) &rd_tmp[rd_ser_len];
306
307   if (zone_key != NULL)
308     memcpy (zone_key_tmp, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
309   else
310   {
311     struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded dummy;
312     memset (&dummy, '0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
313     memcpy (zone_key_tmp, &dummy, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
314   }
315   memcpy (name_tmp, name, name_len);
316   memcpy (rd_tmp, rd_ser, rd_ser_len);
317
318   if (GNUNET_YES == contains_signature)
319     memcpy (signature_tmp, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature));
320   GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, (const struct GNUNET_MessageHeader *) lnr_msg, GNUNET_NO);
321
322   GNUNET_free (lnr_msg);
323 }
324
325 static void handle_lookup_name (void *cls,
326                           struct GNUNET_SERVER_Client * client,
327                           const struct GNUNET_MessageHeader * message)
328 {
329   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_LOOKUP_NAME");
330   struct LookupNameContext lnc;
331   struct GNUNET_NAMESTORE_Client *nc;
332   size_t name_len;
333   char * name;
334   uint32_t rid = 0;
335   uint32_t type = 0;
336   int res;
337
338   if (ntohs (message->size) < sizeof (struct LookupNameMessage))
339   {
340     GNUNET_break_op (0);
341     GNUNET_SERVER_receive_done (client, GNUNET_OK);
342     return;
343   }
344
345   nc = client_lookup(client);
346   if (nc == NULL)
347   {
348     GNUNET_break_op (0);
349     GNUNET_SERVER_receive_done (client, GNUNET_OK);
350     return;
351   }
352
353   struct LookupNameMessage * ln_msg = (struct LookupNameMessage *) message;
354   rid = ntohl (ln_msg->gns_header.r_id);
355   name_len = ntohl (ln_msg->name_len);
356   type = ntohl (ln_msg->record_type);
357
358   if ((name_len == 0) || (name_len > 256))
359   {
360     GNUNET_break_op (0);
361     GNUNET_SERVER_receive_done (client, GNUNET_OK);
362     return;
363   }
364
365   name = (char *) &ln_msg[1];
366   if (name[name_len -1] != '\0')
367   {
368     GNUNET_break_op (0);
369     GNUNET_SERVER_receive_done (client, GNUNET_OK);
370     return;
371   }
372
373   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up record for name `%s' in zone `%s'\n", name, GNUNET_h2s(&ln_msg->zone));
374
375   /* do the actual lookup */
376   lnc.request_id = rid;
377   lnc.nc = nc;
378   lnc.record_type = type;
379   lnc.name = name;
380   lnc.zone = &ln_msg->zone;
381   res = GSN_database->iterate_records(GSN_database->cls, &ln_msg->zone, name, 0, &handle_lookup_name_it, &lnc);
382
383   GNUNET_SERVER_receive_done (client, GNUNET_OK);
384 }
385
386 static void handle_record_put (void *cls,
387                           struct GNUNET_SERVER_Client * client,
388                           const struct GNUNET_MessageHeader * message)
389 {
390   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_PUT");
391   struct GNUNET_NAMESTORE_Client *nc;
392   struct GNUNET_TIME_Absolute expire;
393   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key;
394   struct GNUNET_CRYPTO_RsaSignature *signature;
395   struct RecordPutResponseMessage rpr_msg;
396   size_t name_len;
397   size_t msg_size;
398   size_t msg_size_exp;
399   size_t key_len;
400   char * name;
401   char * rd_ser;
402   uint32_t rid = 0;
403   uint32_t rd_ser_len;
404   uint32_t rd_count;
405   int res = GNUNET_SYSERR;
406
407   if (ntohs (message->size) < sizeof (struct RecordPutMessage))
408   {
409     GNUNET_break_op (0);
410     GNUNET_SERVER_receive_done (client, GNUNET_OK);
411     return;
412   }
413
414   nc = client_lookup (client);
415   if (nc == NULL)
416   {
417     GNUNET_break_op (0);
418     GNUNET_SERVER_receive_done (client, GNUNET_OK);
419     return;
420   }
421
422   struct RecordPutMessage * rp_msg = (struct RecordPutMessage *) message;
423
424   rid = ntohl (rp_msg->gns_header.r_id);
425   msg_size = ntohs (rp_msg->gns_header.header.size);
426   key_len = ntohs (rp_msg->key_len);
427   name_len = ntohs (rp_msg->name_len);
428   rd_count = ntohs (rp_msg->rd_count);
429   rd_ser_len = ntohs(rp_msg->rd_len);
430
431   if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
432   {
433     GNUNET_break_op (0);
434     GNUNET_SERVER_receive_done (client, GNUNET_OK);
435     return;
436   }
437
438   if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
439   {
440     GNUNET_break_op (0);
441     GNUNET_SERVER_receive_done (client, GNUNET_OK);
442     return;
443   }
444
445   msg_size_exp = sizeof (struct RecordPutMessage) + key_len + name_len  + rd_ser_len;
446   if (msg_size != msg_size_exp)
447   {
448     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
449     GNUNET_break_op (0);
450     GNUNET_SERVER_receive_done (client, GNUNET_OK);
451     return;
452   }
453   if ((name_len == 0) || (name_len > 256))
454   {
455     GNUNET_break_op (0);
456     GNUNET_SERVER_receive_done (client, GNUNET_OK);
457     return;
458   }
459
460   zone_key = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &rp_msg[1];
461   name =  &((char *)zone_key)[key_len];
462
463   if (name[name_len -1] != '\0')
464   {
465     GNUNET_break_op (0);
466     GNUNET_SERVER_receive_done (client, GNUNET_OK);
467     return;
468   }
469
470   expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
471   signature = (struct GNUNET_CRYPTO_RsaSignature *) &rp_msg->signature;
472
473   rd_ser = &name[name_len];
474   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
475   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
476   if (res != GNUNET_OK)
477   {
478     GNUNET_break_op (0);
479     goto send;
480   }
481
482
483   GNUNET_HashCode zone_hash;
484   GNUNET_CRYPTO_hash (zone_key, key_len, &zone_hash);
485
486   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting %u record for name `%s' in zone `%s'\n", rd_count, name, GNUNET_h2s(&zone_hash));
487
488   /* Database operation */
489   res = GSN_database->put_records(GSN_database->cls,
490                                 zone_key,
491                                 expire,
492                                 name,
493                                 rd_count, rd,
494                                 signature);
495
496   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting record for name `%s': %s\n",
497       name, (res == GNUNET_OK) ? "OK" : "FAIL");
498
499   /* Send response */
500 send:
501   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_PUT_RESPONSE");
502   rpr_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
503   rpr_msg.op_id = rp_msg->gns_header.r_id;
504   rpr_msg.header.size = htons (sizeof (struct RecordPutResponseMessage));
505   if (GNUNET_OK == res)
506     rpr_msg.op_result = htons (GNUNET_OK);
507   else
508     rpr_msg.op_result = htons (GNUNET_NO);
509   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rpr_msg, GNUNET_NO);
510
511   GNUNET_SERVER_receive_done (client, GNUNET_OK);
512 }
513
514 struct CreateRecordContext
515 {
516   struct GNUNET_NAMESTORE_RecordData *rd;
517   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
518   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
519   struct GNUNET_TIME_Absolute expire;
520   char *name;
521   int res;
522 };
523
524
525 static void
526 handle_create_record_it (void *cls,
527     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
528     struct GNUNET_TIME_Absolute expire,
529     const char *name,
530     unsigned int rd_count,
531     const struct GNUNET_NAMESTORE_RecordData *rd,
532     const struct GNUNET_CRYPTO_RsaSignature *signature)
533 {
534   struct CreateRecordContext * crc = cls;
535   struct GNUNET_CRYPTO_RsaSignature *signature_new;
536   int res;
537
538   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u existing records for `%s'\n", rd_count, crc->name);
539   struct GNUNET_NAMESTORE_RecordData *rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
540   memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
541
542   rd_new[rd_count] = *(crc->rd);
543
544   signature_new = GNUNET_NAMESTORE_create_signature (crc->pkey, crc->name, rd_new, rd_count+1);
545   if (NULL == signature_new)
546   {
547     GNUNET_break (0);
548     res = GNUNET_SYSERR;
549   }
550
551   /* Database operation */
552   res = GSN_database->put_records(GSN_database->cls,
553                                 (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) crc->pubkey,
554                                 crc->expire,
555                                 crc->name,
556                                 rd_count +1, rd_new,
557                                 signature_new);
558   GNUNET_break (GNUNET_OK == res);
559
560   GNUNET_free (rd_new);
561   GNUNET_free (signature_new);
562
563   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %s\n", crc->name, (res == GNUNET_OK) ? "SUCCESS" : "FAIL");
564   crc->res = res;
565 }
566
567 static void handle_record_create (void *cls,
568                           struct GNUNET_SERVER_Client * client,
569                           const struct GNUNET_MessageHeader * message)
570 {
571   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
572   struct GNUNET_NAMESTORE_Client *nc;
573   struct CreateRecordContext crc;
574   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
575   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
576   struct RecordCreateResponseMessage rcr_msg;
577   GNUNET_HashCode pubkey_hash;
578   size_t name_len;
579   size_t msg_size;
580   size_t msg_size_exp;
581   size_t rd_ser_len;
582   size_t key_len;
583   uint32_t rid = 0;
584   char *pkey_tmp;
585   char *name_tmp;
586   char *rd_ser;
587   int rd_count;
588
589   int res = GNUNET_SYSERR;
590
591   if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
592   {
593     GNUNET_break_op (0);
594     GNUNET_SERVER_receive_done (client, GNUNET_OK);
595     return;
596   }
597
598   nc = client_lookup(client);
599   if (nc == NULL)
600   {
601     GNUNET_break_op (0);
602     GNUNET_SERVER_receive_done (client, GNUNET_OK);
603     return;
604   }
605
606   struct RecordCreateMessage * rp_msg = (struct RecordCreateMessage *) message;
607   rid = ntohl (rp_msg->gns_header.r_id);
608   name_len = ntohs (rp_msg->name_len);
609   msg_size = ntohs (message->size);
610   rd_count = ntohs (rp_msg->rd_count);
611   rd_ser_len = ntohs (rp_msg->rd_len);
612   key_len = ntohs (rp_msg->pkey_len);
613   msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
614
615   if (msg_size != msg_size_exp)
616   {
617     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
618     GNUNET_break_op (0);
619     GNUNET_SERVER_receive_done (client, GNUNET_OK);
620     return;
621   }
622
623   if ((name_len == 0) || (name_len > 256))
624   {
625     GNUNET_break_op (0);
626     GNUNET_SERVER_receive_done (client, GNUNET_OK);
627     return;
628   }
629
630   pkey_tmp = (char *) &rp_msg[1];
631   name_tmp = &pkey_tmp[key_len];
632   rd_ser = &name_tmp[name_len];
633
634   if (name_tmp[name_len -1] != '\0')
635   {
636     GNUNET_break_op (0);
637     GNUNET_SERVER_receive_done (client, GNUNET_OK);
638     return;
639   }
640
641   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
642   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
643   if ((res != GNUNET_OK) || (rd_count != 1))
644   {
645     GNUNET_break_op (0);
646     goto send;
647   }
648
649   /* Extracting and converting private key */
650   pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
651   GNUNET_assert (pkey != NULL);
652   GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
653   GNUNET_CRYPTO_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
654
655   crc.pkey = pkey;
656   crc.pubkey = &pub;
657   crc.rd = rd;
658   crc.name = name_tmp;
659
660   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating record for name `%s' in zone `%s'\n", name_tmp, GNUNET_h2s(&pubkey_hash));
661
662   /* Get existing records for name */
663   res = GSN_database->iterate_records(GSN_database->cls, &pubkey_hash, name_tmp, 0, &handle_create_record_it, &crc);
664   if (res != GNUNET_SYSERR)
665     res = GNUNET_OK;
666   GNUNET_CRYPTO_rsa_key_free(pkey);
667
668   /* Send response */
669 send:
670   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
671   rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
672   rcr_msg.gns_header.r_id = htonl (rid);
673   rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
674   if ((GNUNET_OK == res) && (crc.res == GNUNET_OK))
675     rcr_msg.op_result = htons (GNUNET_OK);
676   else
677     rcr_msg.op_result = htons (GNUNET_NO);
678   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO);
679
680   GNUNET_SERVER_receive_done (client, GNUNET_OK);
681 }
682
683
684 struct RemoveRecordContext
685 {
686   struct GNUNET_NAMESTORE_RecordData *rd;
687   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
688   uint16_t op_res;
689 };
690
691 static void
692 handle_record_remove_it (void *cls,
693     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
694     struct GNUNET_TIME_Absolute expire,
695     const char *name,
696     unsigned int rd_count,
697     const struct GNUNET_NAMESTORE_RecordData *rd,
698     const struct GNUNET_CRYPTO_RsaSignature *signature)
699 {
700   struct RemoveRecordContext *rrc = cls;
701   unsigned int rd_count_new = rd_count -1;
702   struct GNUNET_NAMESTORE_RecordData rd_new[rd_count_new];
703   unsigned int c;
704   int res;
705   int found = GNUNET_NO;
706
707   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s 'currently has %u records\n", name, rd_count);
708
709   if (rd_count == 0)
710   {
711     /* Could not find record to remove */
712     rrc->op_res = 1;
713     return;
714   }
715
716   /* Find record to remove */
717   unsigned int c2 = 0;
718   for (c = 0; c < rd_count; c++)
719   {
720     if ((rd[c].expiration.abs_value == rrc->rd->expiration.abs_value) &&
721         (rd[c].flags == rrc->rd->flags) &&
722         (rd[c].record_type == rrc->rd->record_type) &&
723         (rd[c].data_size == rrc->rd->data_size) &&
724         (0 == memcmp (rd[c].data, rrc->rd->data, rrc->rd->data_size)))
725         {
726           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
727           found = GNUNET_YES;
728           continue;
729         }
730     else
731     {
732       rd_new[c2] = rd[c];
733       c2 ++;
734     }
735   }
736   if ((c2 != rd_count_new) || (found == GNUNET_NO))
737   {
738     /* Could not find record to remove */
739     rrc->op_res = 2;
740     return;
741   }
742   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' now has %u records\n", name, rd_count_new);
743
744   /* Create new signature */
745   struct GNUNET_CRYPTO_RsaSignature * new_signature;
746   new_signature = GNUNET_NAMESTORE_create_signature (rrc->pkey, name, rd_new, rd_count_new);
747
748   if (new_signature == NULL)
749   {
750     /* Signature failed */
751     rrc->op_res = 3;
752     return;
753   }
754
755   /* Put records */
756   res = GSN_database->put_records(GSN_database->cls,
757                                   zone_key,
758                                   expire,
759                                   name,
760                                   rd_count_new, rd_new,
761                                   new_signature);
762   GNUNET_free (new_signature);
763
764   if (GNUNET_OK != res)
765   {
766     /* Could put records into database */
767     rrc->op_res = 4;
768     return;
769   }
770
771   rrc->op_res = 0;
772 }
773
774 static void handle_record_remove (void *cls,
775                           struct GNUNET_SERVER_Client * client,
776                           const struct GNUNET_MessageHeader * message)
777 {
778   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE");
779   struct GNUNET_NAMESTORE_Client *nc;
780   struct RecordRemoveResponseMessage rrr_msg;
781   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
782   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
783   GNUNET_HashCode pubkey_hash;
784   char * pkey_tmp = NULL;
785   char * name_tmp = NULL;
786   char * rd_ser = NULL;
787   size_t key_len = 0;
788   size_t name_len = 0;
789   size_t rd_ser_len = 0;
790   size_t msg_size = 0;
791   size_t msg_size_exp = 0;
792   uint32_t rd_count;
793   uint32_t rid = 0;
794
795   int res = GNUNET_SYSERR;
796
797   if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
798   {
799     GNUNET_break_op (0);
800     GNUNET_SERVER_receive_done (client, GNUNET_OK);
801     return;
802   }
803
804   nc = client_lookup(client);
805   if (nc == NULL)
806   {
807     GNUNET_break_op (0);
808     GNUNET_SERVER_receive_done (client, GNUNET_OK);
809     return;
810   }
811
812   struct RecordRemoveMessage * rr_msg = (struct RecordRemoveMessage *) message;
813   rid = ntohl (rr_msg->gns_header.r_id);
814   name_len = ntohs (rr_msg->name_len);
815   rd_ser_len = ntohs (rr_msg->rd_len);
816   rd_count = ntohs (rr_msg->rd_count);
817   key_len = ntohs (rr_msg->key_len);
818   msg_size = ntohs (message->size);
819
820   if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
821   {
822     GNUNET_break_op (0);
823     GNUNET_SERVER_receive_done (client, GNUNET_OK);
824     return;
825   }
826
827   if ((rd_count != 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
828   {
829     GNUNET_break_op (0);
830     GNUNET_SERVER_receive_done (client, GNUNET_OK);
831     return;
832   }
833
834   msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
835   if (msg_size != msg_size_exp)
836   {
837     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
838     GNUNET_break_op (0);
839     GNUNET_SERVER_receive_done (client, GNUNET_OK);
840     return;
841   }
842
843   if ((rd_count != 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
844   {
845     GNUNET_break_op (0);
846     GNUNET_SERVER_receive_done (client, GNUNET_OK);
847     return;
848   }
849
850   pkey_tmp = (char *) &rr_msg[1];
851   name_tmp = &pkey_tmp[key_len];
852   rd_ser = &name_tmp[name_len];
853
854
855   if ((name_len == 0) || (name_len > 256))
856   {
857     GNUNET_break_op (0);
858     GNUNET_SERVER_receive_done (client, GNUNET_OK);
859     return;
860   }
861
862   if (name_tmp[name_len -1] != '\0')
863   {
864     GNUNET_break_op (0);
865     GNUNET_SERVER_receive_done (client, GNUNET_OK);
866     return;
867   }
868
869   /* Extracting and converting private key */
870   pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
871   GNUNET_assert (pkey != NULL);
872   GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
873   GNUNET_CRYPTO_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
874
875   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
876   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
877   if ((res != GNUNET_OK) || (rd_count != 1))
878   {
879     GNUNET_break_op (0);
880     goto send;
881   }
882
883   struct RemoveRecordContext rrc;
884   rrc.rd = rd;
885   rrc.pkey = pkey;
886
887   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s' in zone `%s'\n", name_tmp, GNUNET_h2s(&pubkey_hash));
888
889   /* Database operation */
890   res = GSN_database->iterate_records (GSN_database->cls,
891                                        &pubkey_hash,
892                                        name_tmp,
893                                        0,
894                                        handle_record_remove_it, &rrc);
895
896   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s': %s\n",
897       name_tmp, (rrc.op_res == 0) ? "OK" : "FAIL");
898   res = rrc.op_res;
899
900   /* Send response */
901 send:
902   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE");
903   rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
904   rrr_msg.gns_header.r_id = rr_msg->gns_header.r_id;
905   rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
906   rrr_msg.op_result = htons (res);
907   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO);
908
909   GNUNET_CRYPTO_rsa_key_free (pkey);
910
911   GNUNET_SERVER_receive_done (client, GNUNET_OK);
912 }
913
914 struct ZoneIterationProcResult
915 {
916   int have_zone_key;
917   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key;
918
919   int have_signature;
920   struct GNUNET_CRYPTO_RsaSignature signature;
921   struct GNUNET_TIME_Absolute expire;
922
923   int have_name;
924   char name[256];
925
926   size_t rd_ser_len;
927   char *rd_ser;
928 };
929
930
931 void zone_iteration_proc (void *cls,
932                          const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
933                          struct GNUNET_TIME_Absolute expire,
934                          const char *name,
935                          unsigned int rd_count,
936                          const struct GNUNET_NAMESTORE_RecordData *rd,
937                          const struct GNUNET_CRYPTO_RsaSignature *signature)
938 {
939   struct ZoneIterationProcResult *zipr = cls;
940   size_t len;
941   if (zone_key != NULL)
942   {
943     zipr->zone_key = *zone_key;
944     zipr->have_zone_key = GNUNET_YES;
945   }
946   else
947     zipr->have_zone_key = GNUNET_NO;
948
949   zipr->expire = expire;
950
951   if (name != NULL)
952   {
953     memcpy (zipr->name, name, strlen(name) + 1);
954     zipr->have_name = GNUNET_YES;
955   }
956   else
957     zipr->have_name = GNUNET_NO;
958
959   if (signature != NULL)
960   {
961     zipr->signature = *signature;
962     zipr->have_signature = GNUNET_YES;
963   }
964   else
965     zipr->have_signature = GNUNET_NO;
966
967   if ((rd_count > 0) && (rd != NULL))
968   {
969     len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
970     zipr->rd_ser = GNUNET_malloc (len);
971     GNUNET_NAMESTORE_records_serialize(rd_count, rd, len, zipr->rd_ser);
972     zipr->rd_ser_len = len;
973   }
974 }
975
976 static void handle_iteration_start (void *cls,
977                           struct GNUNET_SERVER_Client * client,
978                           const struct GNUNET_MessageHeader * message)
979 {
980   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
981
982   struct ZoneIterationStartMessage * zis_msg = (struct ZoneIterationStartMessage *) message;
983   struct GNUNET_NAMESTORE_Client *nc;
984   struct GNUNET_NAMESTORE_ZoneIteration *zi;
985   struct ZoneIterationResponseMessage zir_msg;
986   struct ZoneIterationProcResult zipr;
987   int res;
988
989   nc = client_lookup(client);
990   if (nc == NULL)
991   {
992     GNUNET_break_op (0);
993     GNUNET_SERVER_receive_done (client, GNUNET_OK);
994     return;
995   }
996
997   zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
998   zi->request_id = ntohl (zis_msg->gns_header.r_id);
999   zi->offset = 0;
1000   zi->client = nc;
1001   zi->zone = zis_msg->zone;
1002
1003   GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
1004
1005   res = GSN_database->iterate_records (GSN_database->cls, &zis_msg->zone, NULL, zi->offset , &zone_iteration_proc, &zipr);
1006   switch (res) {
1007     case GNUNET_OK:
1008       /* GNUNET_OK on success */
1009
1010       break;
1011     case GNUNET_SYSERR:
1012       /* GNUNET_SYSERR on error */
1013       break;
1014     case GNUNET_NO:
1015       /* GNUNET_NO if there were no results, */
1016       break;
1017     default:
1018       break;
1019   }
1020
1021
1022
1023   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_ITERATION_RESPONSE");
1024   zir_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1025   zir_msg.gns_header.r_id = htonl(zi->request_id);
1026   zir_msg.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1027
1028
1029   GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO);
1030
1031
1032   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1033 }
1034
1035 static void handle_iteration_stop (void *cls,
1036                           struct GNUNET_SERVER_Client * client,
1037                           const struct GNUNET_MessageHeader * message)
1038 {
1039   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_STOP");
1040
1041   struct GNUNET_NAMESTORE_Client *nc;
1042   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1043   struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message;
1044   uint32_t rid;
1045
1046   nc = client_lookup(client);
1047   if (nc == NULL)
1048   {
1049     GNUNET_break_op (0);
1050     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1051     return;
1052   }
1053
1054   rid = ntohl (zis_msg->gns_header.r_id);
1055   for (zi = nc->op_head; zi != NULL; zi = zi->next)
1056   {
1057     if (zi->request_id == rid)
1058       break;
1059   }
1060   if (zi == NULL)
1061   {
1062     GNUNET_break_op (0);
1063     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1064     return;
1065   }
1066
1067   GNUNET_CONTAINER_DLL_remove(nc->op_head, nc->op_tail, zi);
1068   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration for zone `%s'\n", GNUNET_h2s (&zi->zone));
1069   GNUNET_free (zi);
1070
1071   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1072 }
1073
1074 static void handle_iteration_next (void *cls,
1075                           struct GNUNET_SERVER_Client * client,
1076                           const struct GNUNET_MessageHeader * message)
1077 {
1078   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
1079
1080   struct GNUNET_NAMESTORE_Client *nc;
1081   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1082   struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message;
1083   uint32_t rid;
1084   int res;
1085
1086   nc = client_lookup(client);
1087   if (nc == NULL)
1088   {
1089     GNUNET_break_op (0);
1090     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1091     return;
1092   }
1093
1094   rid = ntohl (zis_msg->gns_header.r_id);
1095   for (zi = nc->op_head; zi != NULL; zi = zi->next)
1096   {
1097     if (zi->request_id == rid)
1098       break;
1099   }
1100   if (zi == NULL)
1101   {
1102     GNUNET_break_op (0);
1103     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1104     return;
1105   }
1106
1107   zi->offset++;
1108   res = GSN_database->iterate_records (GSN_database->cls, &zi->zone, NULL, zi->offset , &zone_iteration_proc, zi);
1109 }
1110
1111
1112
1113 /**
1114  * Process template requests.
1115  *
1116  * @param cls closure
1117  * @param server the initialized server
1118  * @param cfg configuration to use
1119  */
1120 static void
1121 run (void *cls, struct GNUNET_SERVER_Handle *server,
1122      const struct GNUNET_CONFIGURATION_Handle *cfg)
1123 {
1124   char * database;
1125
1126   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
1127
1128   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1129     {&handle_start, NULL,
1130      GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
1131     {&handle_lookup_name, NULL,
1132      GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
1133     {&handle_record_put, NULL,
1134     GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
1135     {&handle_record_create, NULL,
1136      GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
1137     {&handle_record_remove, NULL,
1138      GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
1139     {&handle_iteration_start, NULL,
1140      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage)},
1141     {&handle_iteration_stop, NULL,
1142      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, sizeof (struct ZoneIterationStopMessage)},
1143     {&handle_iteration_next, NULL,
1144      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, 0},
1145     {NULL, NULL, 0, 0}
1146   };
1147
1148   GSN_cfg = cfg;
1149
1150   /* Loading database plugin */
1151   if (GNUNET_OK !=
1152       GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
1153                                              &database))
1154     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
1155
1156   GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
1157   GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
1158   if (GSN_database == NULL)
1159     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n",
1160         db_lib_name);
1161   GNUNET_free (database);
1162
1163   /* Configuring server handles */
1164   GNUNET_SERVER_add_handlers (server, handlers);
1165   snc = GNUNET_SERVER_notification_context_create (server, 16);
1166   GNUNET_SERVER_disconnect_notify (server,
1167                                    &client_disconnect_notification,
1168                                    NULL);
1169
1170   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1171                                 NULL);
1172
1173 }
1174
1175
1176 /**
1177  * The main function for the template service.
1178  *
1179  * @param argc number of arguments from the command line
1180  * @param argv command line arguments
1181  * @return 0 ok, 1 on error
1182  */
1183 int
1184 main (int argc, char *const *argv)
1185 {
1186   return (GNUNET_OK ==
1187           GNUNET_SERVICE_run (argc, argv, "namestore",
1188                               GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
1189 }
1190
1191 /* end of gnunet-service-namestore.c */
1192