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