RECLAIM: Start move to GNS encryption
[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 "reclaim_attribute.h"
29 #include "gnunet_reclaim_attribute_plugin.h"
30
31 /**
32  * Handle for a plugin
33  */
34 struct Plugin
35 {
36   /**
37    * Name of the plugin
38    */
39   char *library_name;
40
41   /**
42    * Plugin API
43    */
44   struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api;
45 };
46
47 /**
48  * Plugins
49  */
50 static struct Plugin **attr_plugins;
51
52 /**
53  * Number of plugins
54  */
55 static unsigned int num_plugins;
56
57 /**
58  * Init canary
59  */
60 static int initialized;
61
62 /**
63  * Add a plugin
64  */
65 static void
66 add_plugin (void* cls,
67             const char *library_name,
68             void *lib_ret)
69 {
70   struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api = lib_ret;
71   struct Plugin *plugin;
72
73   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
74               "Loading attribute plugin `%s'\n",
75               library_name);
76   plugin = GNUNET_new (struct Plugin);
77   plugin->api = api;
78   plugin->library_name = GNUNET_strdup (library_name);
79   GNUNET_array_append (attr_plugins, num_plugins, plugin);
80 }
81
82 /**
83  * Load plugins
84  */
85 static void
86 init()
87 {
88   if (GNUNET_YES == initialized)
89     return;
90   initialized = GNUNET_YES;
91   GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_attribute_", NULL,
92                           &add_plugin, NULL);
93 }
94
95 /**
96  * Convert a type name to the corresponding number
97  *
98  * @param typename name to convert
99  * @return corresponding number, UINT32_MAX on error
100  */
101 uint32_t
102 GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (const char *typename)
103 {
104   unsigned int i;
105   struct Plugin *plugin;
106   uint32_t ret;
107
108   init ();
109   for (i = 0; i < num_plugins; i++)
110   {
111     plugin = attr_plugins[i];
112     if (UINT32_MAX != (ret = plugin->api->typename_to_number (plugin->api->cls,
113                                                               typename)))
114       return ret;
115   }
116   return UINT32_MAX;
117 }
118
119 /**
120  * Convert a type number to the corresponding type string
121  *
122  * @param type number of a type
123  * @return corresponding typestring, NULL on error
124  */
125 const char*
126 GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (uint32_t type)
127 {
128   unsigned int i;
129   struct Plugin *plugin;
130   const char *ret;
131
132   init ();
133   for (i = 0; i < num_plugins; i++)
134   {
135     plugin = attr_plugins[i];
136     if (NULL != (ret = plugin->api->number_to_typename (plugin->api->cls,
137                                                         type)))
138       return ret;
139   }
140   return NULL;
141 }
142
143 /**
144  * Convert human-readable version of a 'claim' of an attribute to the binary
145  * representation
146  *
147  * @param type type of the claim
148  * @param s human-readable string
149  * @param data set to value in binary encoding (will be allocated)
150  * @param data_size set to number of bytes in @a data
151  * @return #GNUNET_OK on success
152  */
153 int
154 GNUNET_RECLAIM_ATTRIBUTE_string_to_value (uint32_t type,
155                                           const char *s,
156                                           void **data,
157                                           size_t *data_size)
158 {
159   unsigned int i;
160   struct Plugin *plugin;
161
162   init ();
163   for (i = 0; i < num_plugins; i++)
164   {
165     plugin = attr_plugins[i];
166     if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
167                                                    type,
168                                                    s,
169                                                    data,
170                                                    data_size))
171       return GNUNET_OK;
172   }
173   return GNUNET_SYSERR;
174 }
175
176 /**
177  * Convert the 'claim' of an attribute to a string
178  *
179  * @param type the type of attribute
180  * @param data claim in binary encoding
181  * @param data_size number of bytes in @a data
182  * @return NULL on error, otherwise human-readable representation of the claim
183  */
184 char *
185 GNUNET_RECLAIM_ATTRIBUTE_value_to_string (uint32_t type,
186                                           const void* data,
187                                           size_t data_size)
188 {
189   unsigned int i;
190   struct Plugin *plugin;
191   char *ret;
192
193   init();
194   for (i = 0; i < num_plugins; i++)
195   {
196     plugin = attr_plugins[i];
197     if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
198                                                      type,
199                                                      data,
200                                                      data_size)))
201       return ret;
202   }
203   return NULL;
204 }
205
206 /**
207  * Create a new attribute.
208  *
209  * @param attr_name the attribute name
210  * @param type the attribute type
211  * @param data the attribute value
212  * @param data_size the attribute value size
213  * @return the new attribute
214  */
215 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
216 GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char* attr_name,
217                                     uint32_t type,
218                                     const void* data,
219                                     size_t data_size)
220 {
221   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
222   char *write_ptr;
223   char *attr_name_tmp = GNUNET_strdup (attr_name);
224
225   GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
226
227   attr = GNUNET_malloc (sizeof (struct GNUNET_RECLAIM_ATTRIBUTE_Claim) +
228                         strlen (attr_name_tmp) + 1 +
229                         data_size);
230   attr->type = type;
231   attr->data_size = data_size;
232   attr->version = 0;
233   write_ptr = (char*)&attr[1];
234   GNUNET_memcpy (write_ptr,
235                  attr_name_tmp,
236                  strlen (attr_name_tmp) + 1);
237   attr->name = write_ptr;
238   write_ptr += strlen (attr->name) + 1;
239   GNUNET_memcpy (write_ptr,
240                  data,
241                  data_size);
242   attr->data = write_ptr;
243   GNUNET_free (attr_name_tmp);
244   return attr;
245 }
246
247 /**
248  * Add a new claim list entry.
249  *
250  * @param claim_list the attribute name
251  * @param attr_name the attribute name
252  * @param type the attribute type
253  * @param data the attribute value
254  * @param data_size the attribute value size
255  * @return
256  */
257 void
258 GNUNET_RECLAIM_ATTRIBUTE_list_add (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *claim_list,
259                                    const char* attr_name,
260                                    uint32_t type,
261                                    const void* data,
262                                    size_t data_size)
263 {
264   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
265   le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
266   le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name,
267                                                   type,
268                                                   data,
269                                                   data_size);
270   GNUNET_CONTAINER_DLL_insert (claim_list->list_head,
271                                claim_list->list_tail,
272                                le);
273 }
274
275 size_t
276 GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
277 {
278   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
279   size_t len = 0;
280   for (le = attrs->list_head; NULL != le; le = le->next)
281     len += GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
282   return len;
283 }
284
285 size_t
286 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
287                                          char *result)
288 {
289   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
290   size_t len;
291   size_t total_len;
292   char* write_ptr;
293
294   write_ptr = result;
295   total_len = 0;
296   for (le = attrs->list_head; NULL != le; le = le->next)
297   {
298     len = GNUNET_RECLAIM_ATTRIBUTE_serialize (le->claim,
299                                               write_ptr);
300     total_len += len;
301     write_ptr += len;
302   }
303   return total_len;
304 }
305
306 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
307 GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (const char* data,
308                                            size_t data_size)
309 {
310   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
311   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
312   size_t attr_len;
313   const char* read_ptr;
314
315   if (data_size < sizeof (struct Attribute))
316     return NULL;
317
318   attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
319   read_ptr = data;
320   while (((data + data_size) - read_ptr) >= sizeof (struct Attribute))
321   {
322
323     le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
324     le->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize (read_ptr,
325                                                       data_size - (read_ptr - data));
326     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
327                 "Deserialized attribute %s\n", le->claim->name);
328     GNUNET_CONTAINER_DLL_insert (attrs->list_head,
329                                  attrs->list_tail,
330                                  le);
331     attr_len = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
332     read_ptr += attr_len;
333   }
334   return attrs;
335 }
336
337 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList*
338 GNUNET_RECLAIM_ATTRIBUTE_list_dup (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
339 {
340   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
341   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *result_le;
342   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *result;
343
344   result = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
345   for (le = attrs->list_head; NULL != le; le = le->next)
346   {
347     result_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
348     result_le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (le->claim->name,
349                                                            le->claim->type,
350                                                            le->claim->data,
351                                                            le->claim->data_size);
352     GNUNET_CONTAINER_DLL_insert (result->list_head,
353                                  result->list_tail,
354                                  result_le);
355   }
356   return result;
357 }
358
359
360 void
361 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
362 {
363   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
364   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *tmp_le;
365
366   for (le = attrs->list_head; NULL != le;)
367   {
368     GNUNET_free (le->claim);
369     tmp_le = le;
370     le = le->next;
371     GNUNET_free (tmp_le);
372   }
373   GNUNET_free (attrs);
374
375 }
376
377 size_t
378 GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
379 {
380   return sizeof (struct Attribute)
381     + strlen (attr->name)
382     + attr->data_size;
383 }
384
385 size_t
386 GNUNET_RECLAIM_ATTRIBUTE_serialize (const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
387                                     char *result)
388 {
389   size_t data_len_ser;
390   size_t name_len;
391   struct Attribute *attr_ser;
392   char* write_ptr;
393
394   attr_ser = (struct Attribute*)result;
395   attr_ser->attribute_type = htons (attr->type);
396   attr_ser->attribute_version = htonl (attr->version);
397   attr_ser->attribute_id = GNUNET_htonll (attr->id);
398   name_len = strlen (attr->name);
399   attr_ser->name_len = htons (name_len);
400   write_ptr = (char*)&attr_ser[1];
401   GNUNET_memcpy (write_ptr, attr->name, name_len);
402   write_ptr += name_len;
403   //TODO plugin-ize
404   //data_len_ser = plugin->serialize_attribute_value (attr,
405   //                                                  &attr_ser[1]);
406   data_len_ser = attr->data_size;
407   GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
408   attr_ser->data_size = htons (data_len_ser);
409
410   return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
411 }
412
413 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
414 GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char* data,
415                                       size_t data_size)
416 {
417   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
418   struct Attribute *attr_ser;
419   size_t data_len;
420   size_t name_len;
421   char* write_ptr;
422
423   if (data_size < sizeof (struct Attribute))
424     return NULL;
425
426   attr_ser = (struct Attribute*)data;
427   data_len = ntohs (attr_ser->data_size);
428   name_len = ntohs (attr_ser->name_len);
429   attr = GNUNET_malloc (sizeof (struct GNUNET_RECLAIM_ATTRIBUTE_Claim)
430                         + data_len + name_len + 1);
431   attr->type = ntohs (attr_ser->attribute_type);
432   attr->version = ntohl (attr_ser->attribute_version);
433   attr->id = GNUNET_ntohll (attr_ser->attribute_id);
434   attr->data_size = ntohs (attr_ser->data_size);
435
436   write_ptr =  (char*)&attr[1];
437   GNUNET_memcpy (write_ptr,
438                  &attr_ser[1],
439                  name_len);
440   write_ptr[name_len] = '\0';
441   attr->name = write_ptr;
442
443   write_ptr += name_len + 1;
444   GNUNET_memcpy (write_ptr,
445                  (char*)&attr_ser[1] + name_len,
446                  attr->data_size);
447   attr->data = write_ptr;
448   return attr;
449
450 }
451
452 /* end of reclaim_attribute.c */