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