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