fix warning
[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 /**
222  * Create a new attribute.
223  *
224  * @param attr_name the attribute name
225  * @param type the attribute type
226  * @param data the attribute value
227  * @param data_size the attribute value size
228  * @return the new attribute
229  */
230 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
231 GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char *attr_name,
232                                     uint32_t type,
233                                     const void *data,
234                                     size_t data_size)
235 {
236   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *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_ATTRIBUTE_Claim) +
243                         strlen (attr_name_tmp) + 1 + data_size);
244   attr->type = type;
245   attr->data_size = data_size;
246   attr->version = 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  * Add a new attribute to a claim list
260  *
261  * @param attr_name the name of the new attribute claim
262  * @param type the type of the claim
263  * @param data claim payload
264  * @param data_size claim payload size
265  */
266 void
267 GNUNET_RECLAIM_ATTRIBUTE_list_add (
268   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *claim_list,
269   const char *attr_name,
270   uint32_t type,
271   const void *data,
272   size_t data_size)
273 {
274   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
275   le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
276   le->claim =
277     GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name, type, data, data_size);
278   GNUNET_CONTAINER_DLL_insert (claim_list->list_head,
279                                claim_list->list_tail,
280                                le);
281 }
282
283
284 /**
285  * Get required size for serialization buffer
286  *
287  * @param attrs the attribute list to serialize
288  * @return the required buffer size
289  */
290 size_t
291 GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (
292   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
293 {
294   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
295   size_t len = 0;
296   for (le = attrs->list_head; NULL != le; le = le->next)
297     len += GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
298   return len;
299 }
300
301
302 /**
303  * Serialize an attribute list
304  *
305  * @param attrs the attribute list to serialize
306  * @param result the serialized attribute
307  * @return length of serialized data
308  */
309 size_t
310 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (
311   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
312   char *result)
313 {
314   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
315   size_t len;
316   size_t total_len;
317   char *write_ptr;
318
319   write_ptr = result;
320   total_len = 0;
321   for (le = attrs->list_head; NULL != le; le = le->next)
322   {
323     len = GNUNET_RECLAIM_ATTRIBUTE_serialize (le->claim, write_ptr);
324     total_len += len;
325     write_ptr += len;
326   }
327   return total_len;
328 }
329
330
331 /**
332  * Deserialize an attribute list
333  *
334  * @param data the serialized attribute list
335  * @param data_size the length of the serialized data
336  * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
337  */
338 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
339 GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (const char *data, size_t data_size)
340 {
341   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
342   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
343   size_t attr_len;
344   const char *read_ptr;
345
346   if (data_size < sizeof (struct Attribute))
347     return NULL;
348
349   attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
350   read_ptr = data;
351   while (((data + data_size) - read_ptr) >= sizeof (struct Attribute))
352   {
353
354     le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
355     le->claim =
356       GNUNET_RECLAIM_ATTRIBUTE_deserialize (read_ptr,
357                                             data_size - (read_ptr - data));
358     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
359                 "Deserialized attribute %s\n",
360                 le->claim->name);
361     GNUNET_CONTAINER_DLL_insert (attrs->list_head, attrs->list_tail, le);
362     attr_len = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
363     read_ptr += attr_len;
364   }
365   return attrs;
366 }
367
368
369 /**
370  * Make a (deep) copy of a claim list
371  * @param attrs claim list to copy
372  * @return copied claim list
373  */
374 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
375 GNUNET_RECLAIM_ATTRIBUTE_list_dup (
376   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
377 {
378   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
379   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *result_le;
380   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *result;
381
382   result = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
383   for (le = attrs->list_head; NULL != le; le = le->next)
384   {
385     result_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
386     result_le->claim =
387       GNUNET_RECLAIM_ATTRIBUTE_claim_new (le->claim->name,
388                                           le->claim->type,
389                                           le->claim->data,
390                                           le->claim->data_size);
391     result_le->claim->version = le->claim->version;
392     result_le->claim->id = le->claim->id;
393     GNUNET_CONTAINER_DLL_insert (result->list_head,
394                                  result->list_tail,
395                                  result_le);
396   }
397   return result;
398 }
399
400
401 /**
402  * Destroy claim list
403  *
404  * @param attrs list to destroy
405  */
406 void
407 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (
408   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
409 {
410   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
411   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *tmp_le;
412
413   for (le = attrs->list_head; NULL != le;)
414   {
415     GNUNET_free (le->claim);
416     tmp_le = le;
417     le = le->next;
418     GNUNET_free (tmp_le);
419   }
420   GNUNET_free (attrs);
421 }
422
423
424 /**
425  * Get required size for serialization buffer
426  *
427  * @param attr the attribute to serialize
428  * @return the required buffer size
429  */
430 size_t
431 GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (
432   const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
433 {
434   return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
435 }
436
437
438 /**
439  * Serialize an attribute
440  *
441  * @param attr the attribute to serialize
442  * @param result the serialized attribute
443  * @return length of serialized data
444  */
445 size_t
446 GNUNET_RECLAIM_ATTRIBUTE_serialize (
447   const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
448   char *result)
449 {
450   size_t data_len_ser;
451   size_t name_len;
452   struct Attribute *attr_ser;
453   char *write_ptr;
454
455   attr_ser = (struct Attribute *) result;
456   attr_ser->attribute_type = htons (attr->type);
457   attr_ser->attribute_version = htonl (attr->version);
458   attr_ser->attribute_id = GNUNET_htonll (attr->id);
459   name_len = strlen (attr->name);
460   attr_ser->name_len = htons (name_len);
461   write_ptr = (char *) &attr_ser[1];
462   GNUNET_memcpy (write_ptr, attr->name, name_len);
463   write_ptr += name_len;
464   // TODO plugin-ize
465   // data_len_ser = plugin->serialize_attribute_value (attr,
466   //                                                  &attr_ser[1]);
467   data_len_ser = attr->data_size;
468   GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
469   attr_ser->data_size = htons (data_len_ser);
470
471   return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
472 }
473
474
475 /**
476  * Deserialize an attribute
477  *
478  * @param data the serialized attribute
479  * @param data_size the length of the serialized data
480  *
481  * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
482  */
483 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
484 GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char *data, size_t data_size)
485 {
486   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
487   struct Attribute *attr_ser;
488   size_t data_len;
489   size_t name_len;
490   char *write_ptr;
491
492   if (data_size < sizeof (struct Attribute))
493     return NULL;
494
495   attr_ser = (struct Attribute *) data;
496   data_len = ntohs (attr_ser->data_size);
497   name_len = ntohs (attr_ser->name_len);
498   attr = GNUNET_malloc (sizeof (struct GNUNET_RECLAIM_ATTRIBUTE_Claim) +
499                         data_len + name_len + 1);
500   attr->type = ntohs (attr_ser->attribute_type);
501   attr->version = ntohl (attr_ser->attribute_version);
502   attr->id = GNUNET_ntohll (attr_ser->attribute_id);
503   attr->data_size = ntohs (attr_ser->data_size);
504
505   write_ptr = (char *) &attr[1];
506   GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
507   write_ptr[name_len] = '\0';
508   attr->name = write_ptr;
509
510   write_ptr += name_len + 1;
511   GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, attr->data_size);
512   attr->data = write_ptr;
513   return attr;
514 }
515
516 /* end of reclaim_attribute.c */