- namestore.conf not installed
[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 };
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' in zone `%s'\n", name, GNUNET_h2s(&ln_msg->zone));
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   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
468   if (res != GNUNET_OK)
469   {
470     GNUNET_break_op (0);
471     goto send;
472   }
473
474
475   GNUNET_HashCode zone_hash;
476   GNUNET_CRYPTO_hash (zone_key, key_len, &zone_hash);
477
478   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting %u record for name `%s' in zone `%s'\n", rd_count, name, GNUNET_h2s(&zone_hash));
479
480   /* Database operation */
481   res = GSN_database->put_records(GSN_database->cls,
482                                 zone_key,
483                                 expire,
484                                 name,
485                                 rd_count, rd,
486                                 signature);
487
488   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting record for name `%s': %s\n",
489       name, (res == GNUNET_OK) ? "OK" : "FAIL");
490
491   /* Send response */
492 send:
493   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_PUT_RESPONSE");
494   rpr_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
495   rpr_msg.op_id = rp_msg->gns_header.r_id;
496   rpr_msg.header.size = htons (sizeof (struct RecordPutResponseMessage));
497   if (GNUNET_OK == res)
498     rpr_msg.op_result = htons (GNUNET_OK);
499   else
500     rpr_msg.op_result = htons (GNUNET_NO);
501   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rpr_msg, GNUNET_NO);
502
503   GNUNET_SERVER_receive_done (client, GNUNET_OK);
504 }
505
506 struct CreateRecordContext
507 {
508   struct GNUNET_NAMESTORE_RecordData *rd;
509   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
510   struct GNUNET_TIME_Absolute expire;
511 };
512
513
514 static void
515 handle_create_record_it (void *cls,
516     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
517     struct GNUNET_TIME_Absolute expire,
518     const char *name,
519     unsigned int rd_count,
520     const struct GNUNET_NAMESTORE_RecordData *rd,
521     const struct GNUNET_CRYPTO_RsaSignature *signature)
522 {
523   struct CreateRecordContext * crc = cls;
524   struct GNUNET_CRYPTO_RsaSignature *signature_new;
525   int res;
526
527   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u existing records for `%s'\n", rd_count, name);
528   struct GNUNET_NAMESTORE_RecordData *rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
529   memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
530
531   rd_new[rd_count] = *(crc->rd);
532
533   signature_new = GNUNET_NAMESTORE_create_signature (crc->pkey, name, rd_new, rd_count+1);
534
535   /* Database operation */
536   res = GSN_database->put_records(GSN_database->cls,
537                                 zone_key,
538                                 expire,
539                                 name,
540                                 rd_count +1, rd_new,
541                                 signature_new);
542
543   GNUNET_free (rd_new);
544   GNUNET_free (signature_new);
545
546   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name %u\n", res);
547 }
548
549 static void handle_record_create (void *cls,
550                           struct GNUNET_SERVER_Client * client,
551                           const struct GNUNET_MessageHeader * message)
552 {
553   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
554   struct GNUNET_NAMESTORE_Client *nc;
555   struct CreateRecordContext crc;
556   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
557   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
558   struct RecordCreateResponseMessage rcr_msg;
559   GNUNET_HashCode pubkey_hash;
560   size_t name_len;
561   size_t msg_size;
562   size_t msg_size_exp;
563   size_t rd_ser_len;
564   size_t key_len;
565   uint32_t rid = 0;
566   char *pkey_tmp;
567   char *name_tmp;
568   char *rd_ser;
569   int rd_count;
570
571   int res = GNUNET_SYSERR;
572
573   if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
574   {
575     GNUNET_break_op (0);
576     GNUNET_SERVER_receive_done (client, GNUNET_OK);
577     return;
578   }
579
580   nc = client_lookup(client);
581   if (nc == NULL)
582   {
583     GNUNET_break_op (0);
584     GNUNET_SERVER_receive_done (client, GNUNET_OK);
585     return;
586   }
587
588   struct RecordCreateMessage * rp_msg = (struct RecordCreateMessage *) message;
589   rid = ntohl (rp_msg->gns_header.r_id);
590   name_len = ntohs (rp_msg->name_len);
591   msg_size = ntohs (message->size);
592   rd_count = ntohs (rp_msg->rd_count);
593   rd_ser_len = ntohs (rp_msg->rd_len);
594   key_len = ntohs (rp_msg->pkey_len);
595   msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
596
597   if (msg_size != msg_size_exp)
598   {
599     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
600     GNUNET_break_op (0);
601     GNUNET_SERVER_receive_done (client, GNUNET_OK);
602     return;
603   }
604
605   if ((name_len == 0) || (name_len > 256))
606   {
607     GNUNET_break_op (0);
608     GNUNET_SERVER_receive_done (client, GNUNET_OK);
609     return;
610   }
611
612   pkey_tmp = (char *) &rp_msg[1];
613   name_tmp = &pkey_tmp[key_len];
614   rd_ser = &name_tmp[name_len];
615
616   if (name_tmp[name_len -1] != '\0')
617   {
618     GNUNET_break_op (0);
619     GNUNET_SERVER_receive_done (client, GNUNET_OK);
620     return;
621   }
622
623   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
624   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
625   if (res != GNUNET_OK)
626   {
627     GNUNET_break_op (0);
628     goto send;
629   }
630   GNUNET_assert (rd_count == 1);
631
632   /* Extracting and converting private key */
633   pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
634   GNUNET_assert (pkey != NULL);
635   GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
636   GNUNET_CRYPTO_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
637
638   crc.pkey = pkey;
639   crc.rd = rd;
640
641   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating record for name `%s' in zone `%s'\n", name_tmp, GNUNET_h2s(&pubkey_hash));
642
643   /* Get existing records for name */
644   res = GSN_database->iterate_records(GSN_database->cls, &pubkey_hash, name_tmp, 0, &handle_create_record_it, &crc);
645
646   GNUNET_CRYPTO_rsa_key_free(pkey);
647
648   /* Send response */
649 send:
650   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
651   rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
652   rcr_msg.gns_header.r_id = htonl (rid);
653   rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
654   if (GNUNET_OK == res)
655     rcr_msg.op_result = htons (GNUNET_OK);
656   else
657     rcr_msg.op_result = htons (GNUNET_NO);
658   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO);
659
660   GNUNET_SERVER_receive_done (client, GNUNET_OK);
661 }
662
663
664 struct RemoveRecordContext
665 {
666   struct GNUNET_NAMESTORE_RecordData *rd;
667   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
668   uint16_t op_res;
669 };
670
671 static void
672 handle_record_remove_it (void *cls,
673     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
674     struct GNUNET_TIME_Absolute expire,
675     const char *name,
676     unsigned int rd_count,
677     const struct GNUNET_NAMESTORE_RecordData *rd,
678     const struct GNUNET_CRYPTO_RsaSignature *signature)
679 {
680   struct RemoveRecordContext *rrc = cls;
681   unsigned int rd_count_new = rd_count -1;
682   struct GNUNET_NAMESTORE_RecordData rd_new[rd_count_new];
683   unsigned int c;
684   int res;
685   int found = GNUNET_NO;
686
687   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s 'currently has %u records\n", name, rd_count);
688
689   if (rd_count == 0)
690   {
691     /* Could not find record to remove */
692     rrc->op_res = 1;
693     return;
694   }
695
696   /* Find record to remove */
697   unsigned int c2 = 0;
698   for (c = 0; c < rd_count; c++)
699   {
700     if ((rd[c].expiration.abs_value == rrc->rd->expiration.abs_value) &&
701         (rd[c].flags == rrc->rd->flags) &&
702         (rd[c].record_type == rrc->rd->record_type) &&
703         (rd[c].data_size == rrc->rd->data_size) &&
704         (0 == memcmp (rd[c].data, rrc->rd->data, rrc->rd->data_size)))
705         {
706           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
707           found = GNUNET_YES;
708           continue;
709         }
710     else
711     {
712       rd_new[c2] = rd[c];
713       c2 ++;
714     }
715   }
716   if ((c2 != rd_count_new) || (found == GNUNET_NO))
717   {
718     /* Could not find record to remove */
719     rrc->op_res = 2;
720     return;
721   }
722   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' now has %u records\n", name, rd_count_new);
723
724   /* Create new signature */
725   struct GNUNET_CRYPTO_RsaSignature * new_signature;
726   new_signature = GNUNET_NAMESTORE_create_signature (rrc->pkey, name, rd_new, rd_count_new);
727
728   if (new_signature == NULL)
729   {
730     /* Signature failed */
731     rrc->op_res = 3;
732     return;
733   }
734
735   /* Put records */
736   res = GSN_database->put_records(GSN_database->cls,
737                                   zone_key,
738                                   expire,
739                                   name,
740                                   rd_count_new, rd_new,
741                                   new_signature);
742   GNUNET_free (new_signature);
743
744   if (GNUNET_OK != res)
745   {
746     /* Could put records into database */
747     rrc->op_res = 4;
748     return;
749   }
750
751   rrc->op_res = 0;
752 }
753
754 static void handle_record_remove (void *cls,
755                           struct GNUNET_SERVER_Client * client,
756                           const struct GNUNET_MessageHeader * message)
757 {
758   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE");
759   struct GNUNET_NAMESTORE_Client *nc;
760   struct RecordRemoveResponseMessage rrr_msg;
761   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
762   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
763   GNUNET_HashCode pubkey_hash;
764   char * pkey_tmp = NULL;
765   char * name_tmp = NULL;
766   char * rd_ser = NULL;
767   size_t key_len = 0;
768   size_t name_len = 0;
769   size_t rd_ser_len = 0;
770   size_t msg_size = 0;
771   size_t msg_size_exp = 0;
772   uint32_t rd_count;
773   uint32_t rid = 0;
774
775   int res = GNUNET_SYSERR;
776
777   if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
778   {
779     GNUNET_break_op (0);
780     GNUNET_SERVER_receive_done (client, GNUNET_OK);
781     return;
782   }
783
784   nc = client_lookup(client);
785   if (nc == NULL)
786   {
787     GNUNET_break_op (0);
788     GNUNET_SERVER_receive_done (client, GNUNET_OK);
789     return;
790   }
791
792   struct RecordRemoveMessage * rr_msg = (struct RecordRemoveMessage *) message;
793   rid = ntohl (rr_msg->gns_header.r_id);
794   name_len = ntohs (rr_msg->name_len);
795   rd_ser_len = ntohs (rr_msg->rd_len);
796   rd_count = ntohs (rr_msg->rd_count);
797   key_len = ntohs (rr_msg->key_len);
798   msg_size = ntohs (message->size);
799
800   if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
801   {
802     GNUNET_break_op (0);
803     GNUNET_SERVER_receive_done (client, GNUNET_OK);
804     return;
805   }
806
807   if ((rd_count != 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
808   {
809     GNUNET_break_op (0);
810     GNUNET_SERVER_receive_done (client, GNUNET_OK);
811     return;
812   }
813
814   msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
815   if (msg_size != msg_size_exp)
816   {
817     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
818     GNUNET_break_op (0);
819     GNUNET_SERVER_receive_done (client, GNUNET_OK);
820     return;
821   }
822
823   if ((rd_count != 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
824   {
825     GNUNET_break_op (0);
826     GNUNET_SERVER_receive_done (client, GNUNET_OK);
827     return;
828   }
829
830   pkey_tmp = (char *) &rr_msg[1];
831   name_tmp = &pkey_tmp[key_len];
832   rd_ser = &name_tmp[name_len];
833
834
835   if ((name_len == 0) || (name_len > 256))
836   {
837     GNUNET_break_op (0);
838     GNUNET_SERVER_receive_done (client, GNUNET_OK);
839     return;
840   }
841
842   if (name_tmp[name_len -1] != '\0')
843   {
844     GNUNET_break_op (0);
845     GNUNET_SERVER_receive_done (client, GNUNET_OK);
846     return;
847   }
848
849   /* Extracting and converting private key */
850   pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
851   GNUNET_assert (pkey != NULL);
852   GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
853   GNUNET_CRYPTO_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
854
855   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
856   GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
857   GNUNET_assert (rd_count == 1);
858
859   struct RemoveRecordContext rrc;
860   rrc.rd = rd;
861   rrc.pkey = pkey;
862
863   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s' in zone `%s'\n", name_tmp, GNUNET_h2s(&pubkey_hash));
864
865   /* Database operation */
866   res = GSN_database->iterate_records (GSN_database->cls,
867                                        &pubkey_hash,
868                                        name_tmp,
869                                        0,
870                                        handle_record_remove_it, &rrc);
871
872   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s': %s\n",
873       name_tmp, (rrc.op_res == 0) ? "OK" : "FAIL");
874
875   /* Send response */
876   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE");
877   rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
878   rrr_msg.gns_header.r_id = rr_msg->gns_header.r_id;
879   rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
880   rrr_msg.op_result = htons (rrc.op_res);
881   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO);
882
883   GNUNET_CRYPTO_rsa_key_free (pkey);
884
885   GNUNET_SERVER_receive_done (client, GNUNET_OK);
886 }
887
888 struct ZoneIterationProcResult
889 {
890   int have_zone_key;
891   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key;
892
893   int have_signature;
894   struct GNUNET_CRYPTO_RsaSignature signature;
895   struct GNUNET_TIME_Absolute expire;
896
897   int have_name;
898   char name[256];
899
900   size_t rd_ser_len;
901   char *rd_ser;
902 };
903
904
905 void zone_iteration_proc (void *cls,
906                          const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
907                          struct GNUNET_TIME_Absolute expire,
908                          const char *name,
909                          unsigned int rd_count,
910                          const struct GNUNET_NAMESTORE_RecordData *rd,
911                          const struct GNUNET_CRYPTO_RsaSignature *signature)
912 {
913   struct ZoneIterationProcResult *zipr = cls;
914   size_t len;
915   if (zone_key != NULL)
916   {
917     zipr->zone_key = *zone_key;
918     zipr->have_zone_key = GNUNET_YES;
919   }
920   else
921     zipr->have_zone_key = GNUNET_NO;
922
923   zipr->expire = expire;
924
925   if (name != NULL)
926   {
927     memcpy (zipr->name, name, strlen(name) + 1);
928     zipr->have_name = GNUNET_YES;
929   }
930   else
931     zipr->have_name = GNUNET_NO;
932
933   if (signature != NULL)
934   {
935     zipr->signature = *signature;
936     zipr->have_signature = GNUNET_YES;
937   }
938   else
939     zipr->have_signature = GNUNET_NO;
940
941   if ((rd_count > 0) && (rd != NULL))
942   {
943     len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
944     zipr->rd_ser = GNUNET_malloc (len);
945     GNUNET_NAMESTORE_records_serialize(rd_count, rd, len, zipr->rd_ser);
946     zipr->rd_ser_len = len;
947   }
948 }
949
950 static void handle_iteration_start (void *cls,
951                           struct GNUNET_SERVER_Client * client,
952                           const struct GNUNET_MessageHeader * message)
953 {
954   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
955
956   struct ZoneIterationStartMessage * zis_msg = (struct ZoneIterationStartMessage *) message;
957   struct GNUNET_NAMESTORE_Client *nc;
958   struct GNUNET_NAMESTORE_ZoneIteration *zi;
959   struct ZoneIterationResponseMessage zir_msg;
960   struct ZoneIterationProcResult zipr;
961   int res;
962
963   nc = client_lookup(client);
964   if (nc == NULL)
965   {
966     GNUNET_break_op (0);
967     GNUNET_SERVER_receive_done (client, GNUNET_OK);
968     return;
969   }
970
971   zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
972   zi->request_id = ntohl (zis_msg->gns_header.r_id);
973   zi->offset = 0;
974   zi->client = nc;
975   zi->zone = zis_msg->zone;
976
977   GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
978
979   res = GSN_database->iterate_records (GSN_database->cls, &zis_msg->zone, NULL, zi->offset , &zone_iteration_proc, &zipr);
980   switch (res) {
981     case GNUNET_OK:
982       /* GNUNET_OK on success */
983
984       break;
985     case GNUNET_SYSERR:
986       /* GNUNET_SYSERR on error */
987       break;
988     case GNUNET_NO:
989       /* GNUNET_NO if there were no results, */
990       break;
991     default:
992       break;
993   }
994
995
996
997   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_ITERATION_RESPONSE");
998   zir_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
999   zir_msg.gns_header.r_id = htonl(zi->request_id);
1000   zir_msg.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1001
1002
1003   GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO);
1004
1005
1006   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1007 }
1008
1009 static void handle_iteration_stop (void *cls,
1010                           struct GNUNET_SERVER_Client * client,
1011                           const struct GNUNET_MessageHeader * message)
1012 {
1013   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_STOP");
1014
1015   struct GNUNET_NAMESTORE_Client *nc;
1016   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1017   struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message;
1018   uint32_t rid;
1019
1020   nc = client_lookup(client);
1021   if (nc == NULL)
1022   {
1023     GNUNET_break_op (0);
1024     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1025     return;
1026   }
1027
1028   rid = ntohl (zis_msg->gns_header.r_id);
1029   for (zi = nc->op_head; zi != NULL; zi = zi->next)
1030   {
1031     if (zi->request_id == rid)
1032       break;
1033   }
1034   if (zi == NULL)
1035   {
1036     GNUNET_break_op (0);
1037     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1038     return;
1039   }
1040
1041   GNUNET_CONTAINER_DLL_remove(nc->op_head, nc->op_tail, zi);
1042   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration for zone `%s'\n", GNUNET_h2s (&zi->zone));
1043   GNUNET_free (zi);
1044
1045   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1046 }
1047
1048 static void handle_iteration_next (void *cls,
1049                           struct GNUNET_SERVER_Client * client,
1050                           const struct GNUNET_MessageHeader * message)
1051 {
1052   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
1053
1054   struct GNUNET_NAMESTORE_Client *nc;
1055   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1056   struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message;
1057   uint32_t rid;
1058   int res;
1059
1060   nc = client_lookup(client);
1061   if (nc == NULL)
1062   {
1063     GNUNET_break_op (0);
1064     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1065     return;
1066   }
1067
1068   rid = ntohl (zis_msg->gns_header.r_id);
1069   for (zi = nc->op_head; zi != NULL; zi = zi->next)
1070   {
1071     if (zi->request_id == rid)
1072       break;
1073   }
1074   if (zi == NULL)
1075   {
1076     GNUNET_break_op (0);
1077     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1078     return;
1079   }
1080
1081   zi->offset++;
1082   res = GSN_database->iterate_records (GSN_database->cls, &zi->zone, NULL, zi->offset , &zone_iteration_proc, zi);
1083 }
1084
1085
1086
1087 /**
1088  * Process template requests.
1089  *
1090  * @param cls closure
1091  * @param server the initialized server
1092  * @param cfg configuration to use
1093  */
1094 static void
1095 run (void *cls, struct GNUNET_SERVER_Handle *server,
1096      const struct GNUNET_CONFIGURATION_Handle *cfg)
1097 {
1098   char * database;
1099
1100   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
1101
1102   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1103     {&handle_start, NULL,
1104      GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
1105     {&handle_lookup_name, NULL,
1106      GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
1107     {&handle_record_put, NULL,
1108     GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
1109     {&handle_record_create, NULL,
1110      GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
1111     {&handle_record_remove, NULL,
1112      GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
1113     {&handle_iteration_start, NULL,
1114      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage)},
1115     {&handle_iteration_stop, NULL,
1116      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, sizeof (struct ZoneIterationStopMessage)},
1117     {&handle_iteration_next, NULL,
1118      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, 0},
1119     {NULL, NULL, 0, 0}
1120   };
1121
1122   GSN_cfg = cfg;
1123
1124   /* Loading database plugin */
1125   if (GNUNET_OK !=
1126       GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
1127                                              &database))
1128     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
1129
1130   GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
1131   GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
1132   if (GSN_database == NULL)
1133     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n",
1134         db_lib_name);
1135   GNUNET_free (database);
1136
1137   /* Configuring server handles */
1138   GNUNET_SERVER_add_handlers (server, handlers);
1139   snc = GNUNET_SERVER_notification_context_create (server, 16);
1140   GNUNET_SERVER_disconnect_notify (server,
1141                                    &client_disconnect_notification,
1142                                    NULL);
1143
1144   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1145                                 NULL);
1146
1147 }
1148
1149
1150 /**
1151  * The main function for the template service.
1152  *
1153  * @param argc number of arguments from the command line
1154  * @param argv command line arguments
1155  * @return 0 ok, 1 on error
1156  */
1157 int
1158 main (int argc, char *const *argv)
1159 {
1160   return (GNUNET_OK ==
1161           GNUNET_SERVICE_run (argc, argv, "namestore",
1162                               GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
1163 }
1164
1165 /* end of gnunet-service-namestore.c */
1166