ftbfs
[oweals/gnunet.git] / src / reclaim / reclaim_attestation.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_attestation.c
23  * @brief helper library to manage identity attribute attestations
24  * @author Martin Schanzenbach
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_reclaim_plugin.h"
29 #include "reclaim_attestation.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_AttestationPluginFunctions *api;
46 };
47
48
49 /**
50  * Plugins
51  */
52 static struct Plugin **attest_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_AttestationPluginFunctions *api = lib_ret;
78   struct Plugin *plugin;
79
80   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
81               "Loading attestation 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 (attest_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_attestation_",
100                           NULL,
101                           &add_plugin,
102                           NULL);
103 }
104
105
106 /**
107  * Convert an attestation 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_attestation_typename_to_number (const char *typename)
114 {
115   unsigned int i;
116   struct Plugin *plugin;
117   uint32_t ret;
118   init ();
119   for (i = 0; i < num_plugins; i++)
120   {
121     plugin = attest_plugins[i];
122     if (UINT32_MAX !=
123         (ret = plugin->api->typename_to_number (plugin->api->cls,
124                                                 typename)))
125       return ret;
126   }
127   return UINT32_MAX;
128 }
129
130
131 /**
132  * Convert an attestation type number to the corresponding attestation type string
133  *
134  * @param type number of a type
135  * @return corresponding typestring, NULL on error
136  */
137 const char *
138 GNUNET_RECLAIM_attestation_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 = attest_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 attestation 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_attestation_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 = attest_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 attestation to a string
192  *
193  * @param type the type of attestation
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_attestation_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 = attest_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 /**
222    * Create a new attestation.
223    *
224    * @param attr_name the attestation name
225    * @param type the attestation type
226    * @param data the attestation value
227    * @param data_size the attestation value size
228    * @return the new attestation
229    */
230 struct GNUNET_RECLAIM_Attestation *
231 GNUNET_RECLAIM_attestation_new (const char *attr_name,
232                                 uint32_t type,
233                                 const void *data,
234                                 size_t data_size)
235 {
236   struct GNUNET_RECLAIM_Attestation *attr;
237   char *write_ptr;
238   char *attr_name_tmp = GNUNET_strdup (attr_name);
239
240   GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
241
242   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attestation)
243                         + strlen (attr_name_tmp) + 1 + data_size);
244   attr->type = type;
245   attr->data_size = data_size;
246   attr->flag = 0;
247   write_ptr = (char *) &attr[1];
248   GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
249   attr->name = write_ptr;
250   write_ptr += strlen (attr->name) + 1;
251   GNUNET_memcpy (write_ptr, data, data_size);
252   attr->data = write_ptr;
253   GNUNET_free (attr_name_tmp);
254   return attr;
255 }
256
257
258 /**
259  * Get required size for serialization buffer
260  *
261  * @param attrs the attribute list to serialize
262  * @return the required buffer size
263  */
264 size_t
265 GNUNET_RECLAIM_attestation_list_serialize_get_size (
266   const struct GNUNET_RECLAIM_AttestationList *attestations)
267 {
268   struct GNUNET_RECLAIM_AttestationListEntry *le;
269   size_t len = 0;
270
271   for (le = attestations->list_head; NULL != le; le = le->next)
272   {
273     GNUNET_assert (NULL != le->attestation);
274     len += GNUNET_RECLAIM_attestation_serialize_get_size (le->attestation);
275     len += sizeof(struct GNUNET_RECLAIM_AttestationListEntry);
276   }
277   return len;
278 }
279
280
281 /**
282  * Serialize an attribute list
283  *
284  * @param attrs the attribute list to serialize
285  * @param result the serialized attribute
286  * @return length of serialized data
287  */
288 size_t
289 GNUNET_RECLAIM_attestation_list_serialize (
290   const struct GNUNET_RECLAIM_AttestationList *attestations,
291   char *result)
292 {
293   struct GNUNET_RECLAIM_AttestationListEntry *le;
294   size_t len;
295   size_t total_len;
296   char *write_ptr;
297   write_ptr = result;
298   total_len = 0;
299   for (le = attestations->list_head; NULL != le; le = le->next)
300   {
301     GNUNET_assert (NULL != le->attestation);
302     len = GNUNET_RECLAIM_attestation_serialize (le->attestation, write_ptr);
303     total_len += len;
304     write_ptr += len;
305   }
306   return total_len;
307 }
308
309
310 /**
311  * Deserialize an attestation list
312  *
313  * @param data the serialized attribute list
314  * @param data_size the length of the serialized data
315  * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
316  */
317 struct GNUNET_RECLAIM_AttestationList *
318 GNUNET_RECLAIM_attestation_list_deserialize (const char *data, size_t data_size)
319 {
320   struct GNUNET_RECLAIM_AttestationList *al;
321   struct GNUNET_RECLAIM_AttestationListEntry *ale;
322   size_t att_len;
323   const char *read_ptr;
324
325   al = GNUNET_new (struct GNUNET_RECLAIM_AttestationList);
326
327   if ((data_size < sizeof(struct
328                           Attestation)
329        + sizeof(struct GNUNET_RECLAIM_AttestationListEntry)))
330     return al;
331
332   read_ptr = data;
333   while (((data + data_size) - read_ptr) >= sizeof(struct Attestation))
334   {
335     ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry);
336     ale->attestation =
337       GNUNET_RECLAIM_attestation_deserialize (read_ptr,
338                                               data_size - (read_ptr - data));
339     if (NULL == ale->attestation)
340     {
341       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
342                   "Failed to deserialize malformed attestation.\n");
343       GNUNET_free (ale);
344       return al;
345     }
346     GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
347     att_len = GNUNET_RECLAIM_attestation_serialize_get_size (ale->attestation);
348     read_ptr += att_len;
349   }
350   return al;
351 }
352
353
354 /**
355  * Make a (deep) copy of the attestation list
356  * @param attrs claim list to copy
357  * @return copied claim list
358  */
359 struct GNUNET_RECLAIM_AttestationList *
360 GNUNET_RECLAIM_attestation_list_dup (
361   const struct GNUNET_RECLAIM_AttestationList *al)
362 {
363   struct GNUNET_RECLAIM_AttestationListEntry *ale;
364   struct GNUNET_RECLAIM_AttestationListEntry *result_ale;
365   struct GNUNET_RECLAIM_AttestationList *result;
366
367   result = GNUNET_new (struct GNUNET_RECLAIM_AttestationList);
368   for (ale = al->list_head; NULL != ale; ale = ale->next)
369   {
370     result_ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry);
371     GNUNET_assert (NULL != ale->attestation);
372     result_ale->attestation =
373       GNUNET_RECLAIM_attestation_new (ale->attestation->name,
374                                       ale->attestation->type,
375                                       ale->attestation->data,
376                                       ale->attestation->data_size);
377     result_ale->attestation->id = ale->attestation->id;
378     GNUNET_CONTAINER_DLL_insert (result->list_head,
379                                  result->list_tail,
380                                  result_ale);
381   }
382   return result;
383 }
384
385
386 /**
387  * Destroy attestation list
388  *
389  * @param attrs list to destroy
390  */
391 void
392 GNUNET_RECLAIM_attestation_list_destroy (
393   struct GNUNET_RECLAIM_AttestationList *al)
394 {
395   struct GNUNET_RECLAIM_AttestationListEntry *ale;
396   struct GNUNET_RECLAIM_AttestationListEntry *tmp_ale;
397
398   for (ale = al->list_head; NULL != ale;)
399   {
400     if (NULL != ale->attestation)
401       GNUNET_free (ale->attestation);
402     tmp_ale = ale;
403     ale = ale->next;
404     GNUNET_free (tmp_ale);
405   }
406   GNUNET_free (al);
407 }
408
409
410 /**
411  * Get required size for serialization buffer
412  *
413  * @param attr the attestation to serialize
414  * @return the required buffer size
415  */
416 size_t
417 GNUNET_RECLAIM_attestation_serialize_get_size (
418   const struct GNUNET_RECLAIM_Attestation *attestation)
419 {
420   return sizeof(struct Attestation) + strlen (attestation->name)
421          + attestation->data_size;
422 }
423
424
425 /**
426  * Serialize an attestation
427  *
428  * @param attr the attestation to serialize
429  * @param result the serialized attestation
430  * @return length of serialized data
431  */
432 size_t
433 GNUNET_RECLAIM_attestation_serialize (
434   const struct GNUNET_RECLAIM_Attestation *attestation,
435   char *result)
436 {
437   size_t data_len_ser;
438   size_t name_len;
439   struct Attestation *atts;
440   char *write_ptr;
441
442   atts = (struct Attestation *) result;
443   atts->attestation_type = htons (attestation->type);
444   atts->attestation_flag = htonl (attestation->flag);
445   atts->attestation_id = attestation->id;
446   name_len = strlen (attestation->name);
447   atts->name_len = htons (name_len);
448   write_ptr = (char *) &atts[1];
449   GNUNET_memcpy (write_ptr, attestation->name, name_len);
450   write_ptr += name_len;
451   // TODO plugin-ize
452   // data_len_ser = plugin->serialize_attribute_value (attr,
453   //                                                  &attr_ser[1]);
454   data_len_ser = attestation->data_size;
455   GNUNET_memcpy (write_ptr, attestation->data, attestation->data_size);
456   atts->data_size = htons (data_len_ser);
457
458   return sizeof(struct Attestation) + strlen (attestation->name)
459          + attestation->data_size;
460 }
461
462
463 /**
464  * Deserialize an attestation
465  *
466  * @param data the serialized attestation
467  * @param data_size the length of the serialized data
468  *
469  * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
470  */
471 struct GNUNET_RECLAIM_Attestation *
472 GNUNET_RECLAIM_attestation_deserialize (const char *data, size_t data_size)
473 {
474   struct GNUNET_RECLAIM_Attestation *attestation;
475   struct Attestation *atts;
476   size_t data_len;
477   size_t name_len;
478   char *write_ptr;
479
480   if (data_size < sizeof(struct Attestation))
481     return NULL;
482
483   atts = (struct Attestation *) data;
484   data_len = ntohs (atts->data_size);
485   name_len = ntohs (atts->name_len);
486   if (data_size < sizeof(struct Attestation) + data_len + name_len)
487   {
488     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
489                 "Buffer too small to deserialize\n");
490     return NULL;
491   }
492   attestation = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attestation)
493                                + data_len + name_len + 1);
494   attestation->type = ntohs (atts->attestation_type);
495   attestation->flag = ntohl (atts->attestation_flag);
496   attestation->id = atts->attestation_id;
497   attestation->data_size = data_len;
498
499   write_ptr = (char *) &attestation[1];
500   GNUNET_memcpy (write_ptr, &atts[1], name_len);
501   write_ptr[name_len] = '\0';
502   attestation->name = write_ptr;
503
504   write_ptr += name_len + 1;
505   GNUNET_memcpy (write_ptr, (char *) &atts[1] + name_len,
506                  attestation->data_size);
507   attestation->data = write_ptr;
508   return attestation;
509 }
510
511
512 struct GNUNET_RECLAIM_AttributeList*
513 GNUNET_RECLAIM_attestation_get_attributes (const struct
514                                            GNUNET_RECLAIM_Attestation *attest)
515 {
516   unsigned int i;
517   struct Plugin *plugin;
518   struct GNUNET_RECLAIM_AttributeList *ret;
519   init ();
520   for (i = 0; i < num_plugins; i++)
521   {
522     plugin = attest_plugins[i];
523     if (NULL !=
524         (ret = plugin->api->get_attributes (plugin->api->cls,
525                                             attest)))
526       return ret;
527   }
528   return NULL;
529 }
530
531
532 char*
533 GNUNET_RECLAIM_attestation_get_issuer (const struct
534                                        GNUNET_RECLAIM_Attestation *attest)
535 {
536   unsigned int i;
537   struct Plugin *plugin;
538   char *ret;
539   init ();
540   for (i = 0; i < num_plugins; i++)
541   {
542     plugin = attest_plugins[i];
543     if (NULL !=
544         (ret = plugin->api->get_issuer (plugin->api->cls,
545                                         attest)))
546       return ret;
547   }
548   return NULL;
549 }
550
551
552 int
553 GNUNET_RECLAIM_attestation_get_expiration (const struct
554                                            GNUNET_RECLAIM_Attestation *attest,
555                                            struct GNUNET_TIME_Absolute* exp)
556 {
557   unsigned int i;
558   struct Plugin *plugin;
559   init ();
560   for (i = 0; i < num_plugins; i++)
561   {
562     plugin = attest_plugins[i];
563     if (GNUNET_OK !=  plugin->api->get_expiration (plugin->api->cls,
564                                                    attest,
565                                                    exp))
566       continue;
567     return GNUNET_OK;
568   }
569   return GNUNET_SYSERR;
570 }