43199c1081770af61817513b0bd1e4190f69b7ac
[oweals/gnunet.git] / src / reclaim-attribute / reclaim_attribute.c
1 /*
2    This file is part of GNUnet
3    Copyright (C) 2010-2015 GNUnet e.V.
4
5    GNUnet is free software: you can redistribute it and/or modify it
6    under the terms of the GNU Affero General Public License as published
7    by the Free Software Foundation, either version 3 of the License,
8    or (at your 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    Affero General Public License for more details.
14
15    You should have received a copy of the GNU Affero General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18    SPDX-License-Identifier: AGPL3.0-or-later
19  */
20
21 /**
22  * @file reclaim-attribute/reclaim_attribute.c
23  * @brief helper library to manage identity attributes
24  * @author Martin Schanzenbach
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_reclaim_attribute_plugin.h"
29 #include "reclaim_attribute.h"
30
31
32 /**
33  * Handle for a plugin
34  */
35 struct Plugin
36 {
37   /**
38    * Name of the plugin
39    */
40   char *library_name;
41
42   /**
43    * Plugin API
44    */
45   struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api;
46 };
47
48
49 /**
50  * Plugins
51  */
52 static struct Plugin **attr_plugins;
53
54
55 /**
56  * Number of plugins
57  */
58 static unsigned int num_plugins;
59
60
61 /**
62  * Init canary
63  */
64 static int initialized;
65
66
67 /**
68  * Add a plugin
69  *
70  * @param cls closure
71  * @param library_name name of the API library
72  * @param lib_ret the plugin API pointer
73  */
74 static void
75 add_plugin (void *cls, const char *library_name, void *lib_ret)
76 {
77   struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api = lib_ret;
78   struct Plugin *plugin;
79
80   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
81               "Loading attribute plugin `%s'\n",
82               library_name);
83   plugin = GNUNET_new (struct Plugin);
84   plugin->api = api;
85   plugin->library_name = GNUNET_strdup (library_name);
86   GNUNET_array_append (attr_plugins, num_plugins, plugin);
87 }
88
89
90 /**
91  * Load plugins
92  */
93 static void
94 init ()
95 {
96   if (GNUNET_YES == initialized)
97     return;
98   initialized = GNUNET_YES;
99   GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_attribute_",
100                           NULL,
101                           &add_plugin,
102                           NULL);
103 }
104
105
106 /**
107  * Convert a type name to the corresponding number
108  *
109  * @param typename name to convert
110  * @return corresponding number, UINT32_MAX on error
111  */
112 uint32_t
113 GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (const char *typename)
114 {
115   unsigned int i;
116   struct Plugin *plugin;
117   uint32_t ret;
118
119   init ();
120   for (i = 0; i < num_plugins; i++)
121   {
122     plugin = attr_plugins[i];
123     if (UINT32_MAX !=
124         (ret = plugin->api->typename_to_number (plugin->api->cls, typename)))
125       return ret;
126   }
127   return UINT32_MAX;
128 }
129
130
131 /**
132  * Convert a type number to the corresponding type string
133  *
134  * @param type number of a type
135  * @return corresponding typestring, NULL on error
136  */
137 const char *
138 GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (uint32_t type)
139 {
140   unsigned int i;
141   struct Plugin *plugin;
142   const char *ret;
143
144   init ();
145   for (i = 0; i < num_plugins; i++)
146   {
147     plugin = attr_plugins[i];
148     if (NULL !=
149         (ret = plugin->api->number_to_typename (plugin->api->cls, type)))
150       return ret;
151   }
152   return NULL;
153 }
154
155
156 /**
157  * Convert human-readable version of a 'claim' of an attribute to the binary
158  * representation
159  *
160  * @param type type of the claim
161  * @param s human-readable string
162  * @param data set to value in binary encoding (will be allocated)
163  * @param data_size set to number of bytes in @a data
164  * @return #GNUNET_OK on success
165  */
166 int
167 GNUNET_RECLAIM_ATTRIBUTE_string_to_value (uint32_t type,
168                                           const char *s,
169                                           void **data,
170                                           size_t *data_size)
171 {
172   unsigned int i;
173   struct Plugin *plugin;
174
175   init ();
176   for (i = 0; i < num_plugins; i++)
177   {
178     plugin = attr_plugins[i];
179     if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
180                                                    type,
181                                                    s,
182                                                    data,
183                                                    data_size))
184       return GNUNET_OK;
185   }
186   return GNUNET_SYSERR;
187 }
188
189
190 /**
191  * Convert the 'claim' of an attribute to a string
192  *
193  * @param type the type of attribute
194  * @param data claim in binary encoding
195  * @param data_size number of bytes in @a data
196  * @return NULL on error, otherwise human-readable representation of the claim
197  */
198 char *
199 GNUNET_RECLAIM_ATTRIBUTE_value_to_string (uint32_t type,
200                                           const void *data,
201                                           size_t data_size)
202 {
203   unsigned int i;
204   struct Plugin *plugin;
205   char *ret;
206
207   init ();
208   for (i = 0; i < num_plugins; i++)
209   {
210     plugin = attr_plugins[i];
211     if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
212                                                      type,
213                                                      data,
214                                                      data_size)))
215       return ret;
216   }
217   return NULL;
218 }
219
220 /**
221    * Convert an attestation type name to the corresponding number
222    *
223    * @param typename name to convert
224    * @return corresponding number, UINT32_MAX on error
225    */
226 uint32_t
227 GNUNET_RECLAIM_ATTESTATION_typename_to_number (const char *typename)
228 {
229   unsigned int i;
230   struct Plugin *plugin;
231   uint32_t ret;
232   init ();
233   for (i = 0; i < num_plugins; i++)
234   {
235     plugin = attr_plugins[i];
236     if (UINT32_MAX !=
237         (ret = plugin->api->typename_to_number_attest (plugin->api->cls,
238                                                        typename)))
239       return ret;
240   }
241   return UINT32_MAX;
242 }
243
244 /**
245  * Convert an attestation type number to the corresponding attestation type string
246  *
247  * @param type number of a type
248  * @return corresponding typestring, NULL on error
249  */
250 const char *
251 GNUNET_RECLAIM_ATTESTATION_number_to_typename (uint32_t type)
252 {
253   unsigned int i;
254   struct Plugin *plugin;
255   const char *ret;
256
257   init ();
258   for (i = 0; i < num_plugins; i++)
259   {
260     plugin = attr_plugins[i];
261     if (NULL !=
262         (ret = plugin->api->number_to_typename_attest (plugin->api->cls, type)))
263       return ret;
264   }
265   return NULL;
266 }
267 /**
268  * Convert human-readable version of a 'claim' of an attestation to the binary
269  * representation
270  *
271  * @param type type of the claim
272  * @param s human-readable string
273  * @param data set to value in binary encoding (will be allocated)
274  * @param data_size set to number of bytes in @a data
275  * @return #GNUNET_OK on success
276  */
277 int
278 GNUNET_RECLAIM_ATTESTATION_string_to_value (uint32_t type,
279                                             const char *s,
280                                             void **data,
281                                             size_t *data_size)
282 {
283   unsigned int i;
284   struct Plugin *plugin;
285
286   init ();
287   for (i = 0; i < num_plugins; i++)
288   {
289     plugin = attr_plugins[i];
290     if (GNUNET_OK == plugin->api->string_to_value_attest (plugin->api->cls,
291                                                           type,
292                                                           s,
293                                                           data,
294                                                           data_size))
295       return GNUNET_OK;
296   }
297   return GNUNET_SYSERR;
298 }
299
300
301 /**
302  * Convert the 'claim' of an attestation to a string
303  *
304  * @param type the type of attestation
305  * @param data claim in binary encoding
306  * @param data_size number of bytes in @a data
307  * @return NULL on error, otherwise human-readable representation of the claim
308  */
309 char *
310 GNUNET_RECLAIM_ATTESTATION_value_to_string (uint32_t type,
311                                             const void *data,
312                                             size_t data_size)
313 {
314   unsigned int i;
315   struct Plugin *plugin;
316   char *ret;
317
318   init ();
319   for (i = 0; i < num_plugins; i++)
320   {
321     plugin = attr_plugins[i];
322     if (NULL != (ret = plugin->api->value_to_string_attest (plugin->api->cls,
323                                                             type,
324                                                             data,
325                                                             data_size)))
326       return ret;
327   }
328   return NULL;
329 }
330
331 /**
332  * Create a new attribute.
333  *
334  * @param attr_name the attribute name
335  * @param type the attribute type
336  * @param data the attribute value
337  * @param data_size the attribute value size
338  * @return the new attribute
339  */
340 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
341 GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char *attr_name,
342                                     uint32_t type,
343                                     const void *data,
344                                     size_t data_size)
345 {
346   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
347   char *write_ptr;
348   char *attr_name_tmp = GNUNET_strdup (attr_name);
349
350   GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
351
352   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_Claim)
353                         + strlen (attr_name_tmp) + 1 + data_size);
354   attr->type = type;
355   attr->data_size = data_size;
356   attr->flag = 0;
357   write_ptr = (char *) &attr[1];
358   GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
359   attr->name = write_ptr;
360   write_ptr += strlen (attr->name) + 1;
361   GNUNET_memcpy (write_ptr, data, data_size);
362   attr->data = write_ptr;
363   GNUNET_free (attr_name_tmp);
364   return attr;
365 }
366
367 /**
368    * Create a new attestation.
369    *
370    * @param attr_name the attestation name
371    * @param type the attestation type
372    * @param data the attestation value
373    * @param data_size the attestation value size
374    * @return the new attestation
375    */
376 struct GNUNET_RECLAIM_ATTESTATION_Claim *
377 GNUNET_RECLAIM_ATTESTATION_claim_new (const char *attr_name,
378                                       uint32_t type,
379                                       const void *data,
380                                       size_t data_size)
381 {
382   struct GNUNET_RECLAIM_ATTESTATION_Claim *attr;
383   char *write_ptr;
384   char *attr_name_tmp = GNUNET_strdup (attr_name);
385
386   GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
387
388   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim)
389                         + strlen (attr_name_tmp) + 1 + data_size);
390   attr->type = type;
391   attr->data_size = data_size;
392   attr->version = 0;
393   write_ptr = (char *) &attr[1];
394   GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
395   attr->name = write_ptr;
396   write_ptr += strlen (attr->name) + 1;
397   GNUNET_memcpy (write_ptr, data, data_size);
398   attr->data = write_ptr;
399   GNUNET_free (attr_name_tmp);
400   return attr;
401 }
402
403 /**
404  * Create a new attestation reference.
405  *
406  * @param attr_name the referenced claim name
407  * @param ref_value the claim name in the attestation
408  * @return the new reference
409  */
410 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *
411 GNUNET_RECLAIM_ATTESTATION_reference_new (const char *attr_name,
412                                           const char *ref_value)
413 {
414   struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
415   char *write_ptr;
416   char *attr_name_tmp = GNUNET_strdup (attr_name);
417   char *ref_value_tmp = GNUNET_strdup (ref_value);
418
419   GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
420   GNUNET_STRINGS_utf8_tolower (ref_value, ref_value_tmp);
421
422   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_REFERENCE)
423                         + strlen (attr_name_tmp) + strlen (ref_value_tmp) + 2);
424
425   write_ptr = (char *) &attr[1];
426   GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
427   attr->name = write_ptr;
428
429   write_ptr += strlen (attr_name) + 1;
430   GNUNET_memcpy (write_ptr, ref_value_tmp, strlen (ref_value_tmp) + 1);
431   attr->reference_value = write_ptr;
432
433   GNUNET_free (attr_name_tmp);
434   GNUNET_free (ref_value_tmp);
435   return attr;
436 }
437
438 /**
439  * Add a new attribute to a claim list
440  *
441  * @param attr_name the name of the new attribute claim
442  * @param type the type of the claim
443  * @param data claim payload
444  * @param data_size claim payload size
445  */
446 void
447 GNUNET_RECLAIM_ATTRIBUTE_list_add (
448   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *claim_list,
449   const char *attr_name,
450   uint32_t type,
451   const void *data,
452   size_t data_size)
453 {
454   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
455
456   le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
457   le->claim =
458     GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name, type, data, data_size);
459   GNUNET_CONTAINER_DLL_insert (claim_list->list_head,
460                                claim_list->list_tail,
461                                le);
462 }
463
464
465 /**
466  * Get required size for serialization buffer
467  *
468  * @param attrs the attribute list to serialize
469  * @return the required buffer size
470  */
471 size_t
472 GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (
473   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
474 {
475   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
476   size_t len = 0;
477
478   for (le = attrs->list_head; NULL != le; le = le->next)
479   {
480     if (NULL != le->claim)
481     {
482       len += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
483       len += GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
484     }
485     else if (NULL != le->attest )
486     {
487       len += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
488       len += GNUNET_RECLAIM_ATTESTATION_serialize_get_size (le->attest);
489     }
490     else if (NULL != le->reference)
491     {
492       len += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
493       len += GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (le->reference);
494     }
495     else
496     {
497       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
498                   "Unserialized Claim List Entry Type for size not known.\n");
499       break;
500     }
501     len += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
502   }
503   return len;
504 }
505
506
507 /**
508  * Serialize an attribute list
509  *
510  * @param attrs the attribute list to serialize
511  * @param result the serialized attribute
512  * @return length of serialized data
513  */
514 size_t
515 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (
516   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
517   char *result)
518 {
519   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
520   size_t len;
521   size_t total_len;
522   char *write_ptr;
523   write_ptr = result;
524   total_len = 0;
525   for (le = attrs->list_head; NULL != le; le = le->next)
526   {
527     struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType *list_type;
528     if (NULL != le->claim)
529     {
530       list_type = (struct
531                    GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType *) write_ptr;
532       list_type->type = htons (1);
533       total_len += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
534       write_ptr += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
535       len = GNUNET_RECLAIM_ATTRIBUTE_serialize (le->claim, write_ptr);
536       total_len += len;
537       write_ptr += len;
538     }
539     else if (NULL != le->attest )
540     {
541       list_type = (struct
542                    GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType *) write_ptr;
543       list_type->type = htons (2);
544       total_len += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
545       write_ptr += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
546       len = GNUNET_RECLAIM_ATTESTATION_serialize (le->attest, write_ptr);
547       total_len += len;
548       write_ptr += len;
549     }
550     else if (NULL != le->reference)
551     {
552       list_type = (struct
553                    GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType *) write_ptr;
554       list_type->type = htons (3);
555       total_len += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
556       write_ptr += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
557       len = GNUNET_RECLAIM_ATTESTATION_REF_serialize (le->reference, write_ptr);
558       total_len += len;
559       write_ptr += len;
560     }
561     else
562     {
563       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
564                   "Unserialized Claim List Entry Type not known.\n");
565       continue;
566     }
567   }
568   return total_len;
569 }
570
571
572 /**
573  * Deserialize an attribute list
574  *
575  * @param data the serialized attribute list
576  * @param data_size the length of the serialized data
577  * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
578  */
579 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
580 GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (const char *data, size_t data_size)
581 {
582   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
583   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
584   size_t attr_len;
585   const char *read_ptr;
586
587   if ((data_size < sizeof(struct Attribute) + sizeof(struct
588                                                      GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry))
589       && (data_size < sizeof(struct
590                              Attestation)
591           + sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry)) &&
592       (data_size < sizeof(struct Attestation_Reference) + sizeof(struct
593                                                                  GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry)) )
594     return NULL;
595
596   attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
597   read_ptr = data;
598   while (((data + data_size) - read_ptr) >= sizeof(struct Attribute))
599   {
600     struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType *list_type;
601     list_type = (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType *) read_ptr;
602     if (1 == ntohs (list_type->type))
603     {
604       le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
605       read_ptr += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
606       if (((data + data_size) - read_ptr) < sizeof(struct Attribute))
607         break;
608       le->attest = NULL;
609       le->reference = NULL;
610       le->claim =
611         GNUNET_RECLAIM_ATTRIBUTE_deserialize (read_ptr,
612                                               data_size - (read_ptr - data));
613       GNUNET_CONTAINER_DLL_insert (attrs->list_head, attrs->list_tail, le);
614       attr_len = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
615       read_ptr += attr_len;
616     }
617     else if (2 == ntohs (list_type->type))
618     {
619       le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
620       read_ptr += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
621       if (((data + data_size) - read_ptr) < sizeof(struct Attestation))
622         break;
623       le->claim = NULL;
624       le->reference = NULL;
625       le->attest =
626         GNUNET_RECLAIM_ATTESTATION_deserialize (read_ptr,
627                                                 data_size - (read_ptr - data));
628       GNUNET_CONTAINER_DLL_insert (attrs->list_head, attrs->list_tail, le);
629       attr_len = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (le->attest);
630       read_ptr += attr_len;
631     }
632     else if (3 == ntohs (list_type->type))
633     {
634       le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
635       read_ptr += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
636       if (((data + data_size) - read_ptr) < sizeof(struct
637                                                    Attestation_Reference))
638         break;
639       le->claim = NULL;
640       le->attest = NULL;
641       le->reference =
642         GNUNET_RECLAIM_ATTESTATION_REF_deserialize (read_ptr,
643                                                     data_size - (read_ptr
644                                                                  - data));
645       GNUNET_CONTAINER_DLL_insert (attrs->list_head, attrs->list_tail, le);
646       attr_len = GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (
647         le->reference);
648       read_ptr += attr_len;
649     }
650     else
651     {
652       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
653                   "Serialized Claim List Entry Type not known.\n");
654       break;
655     }
656   }
657   return attrs;
658 }
659
660
661 /**
662  * Make a (deep) copy of a claim list
663  * @param attrs claim list to copy
664  * @return copied claim list
665  */
666 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
667 GNUNET_RECLAIM_ATTRIBUTE_list_dup (
668   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
669 {
670   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
671   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *result_le;
672   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *result;
673
674   result = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
675   if (NULL == attrs->list_head)
676   {
677     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Duplicating empty List\n");
678   }
679   for (le = attrs->list_head; NULL != le; le = le->next)
680   {
681     result_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
682     result_le->claim = NULL;
683     result_le->attest = NULL;
684     result_le->reference = NULL;
685     if (NULL != le->claim)
686     {
687       result_le->claim =
688         GNUNET_RECLAIM_ATTRIBUTE_claim_new (le->claim->name,
689                                             le->claim->type,
690                                             le->claim->data,
691                                             le->claim->data_size);
692
693       result_le->claim->id = le->claim->id;
694       result_le->claim->flag = le->claim->flag;
695     }
696     if ( NULL != le->attest)
697     {
698       result_le->attest = GNUNET_RECLAIM_ATTESTATION_claim_new (
699         le->attest->name,
700         le->attest->type,
701         le->attest->data,
702         le->attest->
703         data_size);
704       result_le->attest->id = le->attest->id;
705     }
706     if (NULL !=le->reference)
707     {
708       result_le->reference = GNUNET_RECLAIM_ATTESTATION_reference_new (
709         le->reference->name,
710         le->reference->reference_value);
711       result_le->reference->id = le->reference->id;
712       result_le->reference->id_attest = le->reference->id_attest;
713     }
714     GNUNET_CONTAINER_DLL_insert (result->list_head,
715                                  result->list_tail,
716                                  result_le);
717   }
718   return result;
719 }
720
721
722 /**
723  * Destroy claim list
724  *
725  * @param attrs list to destroy
726  */
727 void
728 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (
729   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
730 {
731   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
732   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *tmp_le;
733
734   for (le = attrs->list_head; NULL != le; le = le->next)
735   {
736     if (NULL != le->claim)
737       GNUNET_free (le->claim);
738     if (NULL != le->attest)
739       GNUNET_free (le->attest);
740     if (NULL != le->reference)
741       GNUNET_free (le->reference);
742     tmp_le = le;
743     le = le->next;
744     GNUNET_free (tmp_le);
745   }
746   GNUNET_free (attrs);
747 }
748
749 /**
750  * Count attestations in claim list
751  *
752  * @param attrs list
753  */
754 int
755 GNUNET_RECLAIM_ATTRIBUTE_list_count_attest (
756   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
757 {
758   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
759   int i = 0;
760   for (le = attrs->list_head; NULL != le; le = le->next)
761   {
762     if (NULL != le->attest)
763       i++;
764   }
765   return i;
766 }
767 /**
768  * Get required size for serialization buffer
769  *
770  * @param attr the attribute to serialize
771  * @return the required buffer size
772  */
773 size_t
774 GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (
775   const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
776 {
777   return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
778 }
779
780
781 /**
782  * Serialize an attribute
783  *
784  * @param attr the attribute to serialize
785  * @param result the serialized attribute
786  * @return length of serialized data
787  */
788 size_t
789 GNUNET_RECLAIM_ATTRIBUTE_serialize (
790   const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
791   char *result)
792 {
793   size_t data_len_ser;
794   size_t name_len;
795   struct Attribute *attr_ser;
796   char *write_ptr;
797
798   attr_ser = (struct Attribute *) result;
799   attr_ser->attribute_type = htons (attr->type);
800   attr_ser->attribute_version = htonl (attr->flag);
801   attr_ser->attribute_id = GNUNET_htonll (attr->id);
802   name_len = strlen (attr->name);
803   attr_ser->name_len = htons (name_len);
804   write_ptr = (char *) &attr_ser[1];
805   GNUNET_memcpy (write_ptr, attr->name, name_len);
806   write_ptr += name_len;
807   // TODO plugin-ize
808   // data_len_ser = plugin->serialize_attribute_value (attr,
809   //                                                  &attr_ser[1]);
810   data_len_ser = attr->data_size;
811   GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
812   attr_ser->data_size = htons (data_len_ser);
813
814   return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
815 }
816
817
818 /**
819  * Deserialize an attribute
820  *
821  * @param data the serialized attribute
822  * @param data_size the length of the serialized data
823  *
824  * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
825  */
826 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
827 GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char *data, size_t data_size)
828 {
829   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
830   struct Attribute *attr_ser;
831   size_t data_len;
832   size_t name_len;
833   char *write_ptr;
834
835   if (data_size < sizeof(struct Attribute))
836     return NULL;
837
838   attr_ser = (struct Attribute *) data;
839   data_len = ntohs (attr_ser->data_size);
840   name_len = ntohs (attr_ser->name_len);
841   if (data_size < sizeof(struct Attribute) + data_len + name_len)
842   {
843     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
844                 "Buffer too small to deserialize\n");
845     return NULL;
846   }
847   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_Claim)
848                         + data_len + name_len + 1);
849   attr->type = ntohs (attr_ser->attribute_type);
850   attr->flag = ntohl (attr_ser->attribute_version);
851   attr->id = GNUNET_ntohll (attr_ser->attribute_id);
852   attr->data_size = data_len;
853
854   write_ptr = (char *) &attr[1];
855   GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
856   write_ptr[name_len] = '\0';
857   attr->name = write_ptr;
858
859   write_ptr += name_len + 1;
860   GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, attr->data_size);
861   attr->data = write_ptr;
862   return attr;
863 }
864
865
866 /**
867  * Get required size for serialization buffer
868  *
869  * @param attr the attestation to serialize
870  * @return the required buffer size
871  */
872 size_t
873 GNUNET_RECLAIM_ATTESTATION_serialize_get_size (
874   const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr)
875 {
876   return sizeof(struct Attestation) + strlen (attr->name) + attr->data_size;
877 }
878
879 /**
880  * Serialize an attestation
881  *
882  * @param attr the attestation to serialize
883  * @param result the serialized attestation
884  * @return length of serialized data
885  */
886 size_t
887 GNUNET_RECLAIM_ATTESTATION_serialize (
888   const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr,
889   char *result)
890 {
891   size_t data_len_ser;
892   size_t name_len;
893   struct Attestation *attr_ser;
894   char *write_ptr;
895
896   attr_ser = (struct Attestation *) result;
897   attr_ser->attestation_type = htons (attr->type);
898   attr_ser->attestation_version = htonl (attr->version);
899   attr_ser->attestation_id = GNUNET_htonll (attr->id);
900   name_len = strlen (attr->name);
901   attr_ser->name_len = htons (name_len);
902   write_ptr = (char *) &attr_ser[1];
903   GNUNET_memcpy (write_ptr, attr->name, name_len);
904   write_ptr += name_len;
905   // TODO plugin-ize
906   // data_len_ser = plugin->serialize_attribute_value (attr,
907   //                                                  &attr_ser[1]);
908   data_len_ser = attr->data_size;
909   GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
910   attr_ser->data_size = htons (data_len_ser);
911
912   return sizeof(struct Attestation) + strlen (attr->name) + attr->data_size;
913 }
914
915 /**
916  * Deserialize an attestation
917  *
918  * @param data the serialized attestation
919  * @param data_size the length of the serialized data
920  *
921  * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
922  */
923 struct GNUNET_RECLAIM_ATTESTATION_Claim *
924 GNUNET_RECLAIM_ATTESTATION_deserialize (const char *data, size_t data_size)
925 {
926   struct GNUNET_RECLAIM_ATTESTATION_Claim *attr;
927   struct Attestation *attr_ser;
928   size_t data_len;
929   size_t name_len;
930   char *write_ptr;
931
932   if (data_size < sizeof(struct Attestation))
933     return NULL;
934
935   attr_ser = (struct Attestation *) data;
936   data_len = ntohs (attr_ser->data_size);
937   name_len = ntohs (attr_ser->name_len);
938   if (data_size < sizeof(struct Attestation) + data_len + name_len)
939   {
940     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
941                 "Buffer too small to deserialize\n");
942     return NULL;
943   }
944   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim)
945                         + data_len + name_len + 1);
946   attr->type = ntohs (attr_ser->attestation_type);
947   attr->version = ntohl (attr_ser->attestation_version);
948   attr->id = GNUNET_ntohll (attr_ser->attestation_id);
949   attr->data_size = data_len;
950
951   write_ptr = (char *) &attr[1];
952   GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
953   write_ptr[name_len] = '\0';
954   attr->name = write_ptr;
955
956   write_ptr += name_len + 1;
957   GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, attr->data_size);
958   attr->data = write_ptr;
959   return attr;
960 }
961
962 /**
963  * Get required size for serialization buffer
964  *
965  * @param attr the reference to serialize
966  * @return the required buffer size
967  */
968 size_t
969 GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (
970   const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr)
971 {
972   return sizeof(struct Attestation_Reference) + strlen (attr->name) + strlen (
973     attr->reference_value);
974 }
975
976
977 /**
978  * Serialize a reference
979  *
980  * @param attr the reference to serialize
981  * @param result the serialized reference
982  * @return length of serialized data
983  */
984 size_t
985 GNUNET_RECLAIM_ATTESTATION_REF_serialize (
986   const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr,
987   char *result)
988 {
989   size_t name_len;
990   size_t refval_len;
991   struct Attestation_Reference *attr_ser;
992   char *write_ptr;
993   attr_ser = (struct Attestation_Reference *) result;
994   attr_ser->reference_id = GNUNET_htonll (attr->id);
995   attr_ser->attestation_id = GNUNET_htonll (attr->id_attest);
996   name_len = strlen (attr->name);
997   refval_len = strlen (attr->reference_value);
998   attr_ser->name_len = htons (name_len);
999   attr_ser->ref_value_len = htons (refval_len);
1000   write_ptr = (char *) &attr_ser[1];
1001   GNUNET_memcpy (write_ptr, attr->name, name_len);
1002   write_ptr += name_len;
1003   GNUNET_memcpy (write_ptr, attr->reference_value, refval_len);
1004
1005   return sizeof(struct Attestation_Reference) + strlen (attr->name) + strlen (
1006     attr->reference_value);
1007 }
1008
1009
1010 /**
1011  * Deserialize a reference
1012  *
1013  * @param data the serialized reference
1014  * @param data_size the length of the serialized data
1015  *
1016  * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
1017  */
1018 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *
1019 GNUNET_RECLAIM_ATTESTATION_REF_deserialize (const char *data, size_t data_size)
1020 {
1021   struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
1022   struct Attestation_Reference *attr_ser;
1023   size_t name_len;
1024   size_t refval_len;
1025   char *write_ptr;
1026
1027   if (data_size < sizeof(struct Attestation_Reference))
1028     return NULL;
1029   attr_ser = (struct Attestation_Reference *) data;
1030   name_len = ntohs (attr_ser->name_len);
1031   refval_len = ntohs (attr_ser->ref_value_len);
1032   if (data_size < sizeof(struct Attestation_Reference) + refval_len + name_len)
1033   {
1034     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1035                 "Buffer too small to deserialize\n");
1036     return NULL;
1037   }
1038   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_REFERENCE)
1039                         + refval_len + name_len + 2);
1040
1041   attr->id = GNUNET_ntohll (attr_ser->reference_id);
1042   attr->id_attest = GNUNET_ntohll (attr_ser->attestation_id);
1043
1044   write_ptr = (char *) &attr[1];
1045   GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
1046   write_ptr[name_len] = '\0';
1047   attr->name = write_ptr;
1048
1049   write_ptr += name_len + 1;
1050   GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, refval_len);
1051   write_ptr[refval_len] = '\0';
1052   attr->reference_value = write_ptr;
1053   return attr;
1054 }
1055 /* end of reclaim_attribute.c */