0111668feba6ee58949aa07104dc58f15679cf5b
[oweals/gnunet.git] / src / identity-attribute / identity_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
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., 51 Franklin Street, Fifth Floor,
18       Boston, MA 02110-1301, USA.
19  */
20
21 /**
22  * @file identity-attribute/identity_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 "identity_attribute.h"
29 #include "gnunet_identity_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_IDENTITY_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_IDENTITY_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_identity_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_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_ATTRIBUTE_Claim *
216 GNUNET_IDENTITY_ATTRIBUTE_claim_new (const char* attr_name,
217                uint32_t type,
218                const void* data,
219                size_t data_size)
220 {
221   struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
222   char *write_ptr;
223
224   attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim) +
225                         strlen (attr_name) + 1 +
226                         data_size);
227   attr->type = type;
228   attr->data_size = data_size;
229   attr->version = 0;
230   write_ptr = (char*)&attr[1];
231   GNUNET_memcpy (write_ptr,
232                  attr_name,
233                  strlen (attr_name) + 1);
234   attr->name = write_ptr;
235   write_ptr += strlen (attr->name) + 1;
236   GNUNET_memcpy (write_ptr,
237                  data,
238                  data_size);
239   attr->data = write_ptr;
240   return attr;
241 }
242
243 /**
244  * Add a new claim list entry.
245  *
246  * @param claim_list the attribute name
247  * @param attr_name the attribute name
248  * @param type the attribute type
249  * @param data the attribute value
250  * @param data_size the attribute value size
251  * @return
252  */
253 void
254 GNUNET_IDENTITY_ATTRIBUTE_list_add (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *claim_list,
255                                     const char* attr_name,
256                                     uint32_t type,
257                                     const void* data,
258                                     size_t data_size)
259 {
260   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
261   le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
262   le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr_name,
263                                                type,
264                                                data,
265                                                data_size);
266   GNUNET_CONTAINER_DLL_insert (claim_list->list_head,
267                                claim_list->list_tail,
268                                le);
269 }
270
271 size_t
272 GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
273 {
274   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
275   size_t len = 0;
276   for (le = attrs->list_head; NULL != le; le = le->next)
277     len += GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (le->claim);
278   return len; 
279 }
280
281 size_t
282 GNUNET_IDENTITY_ATTRIBUTE_list_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
283                           char *result)
284 {
285   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
286   size_t len;
287   size_t total_len;
288   char* write_ptr;
289
290   write_ptr = result;
291   total_len = 0;
292   for (le = attrs->list_head; NULL != le; le = le->next)
293   {
294     len = GNUNET_IDENTITY_ATTRIBUTE_serialize (le->claim,
295                                write_ptr);
296     total_len += len;
297     write_ptr += len;
298   }
299   return total_len;
300 }
301
302 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *
303 GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (const char* data,
304                        size_t data_size)
305 {
306   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
307   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
308   size_t attr_len;
309   const char* read_ptr;
310
311   if (data_size < sizeof (struct Attribute))
312     return NULL;
313   
314   attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
315   read_ptr = data;
316   while (((data + data_size) - read_ptr) >= sizeof (struct Attribute))
317   {
318
319     le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
320     le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (read_ptr,
321                                            data_size - (read_ptr - data));
322     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
323                 "Deserialized attribute %s\n", le->claim->name);
324     GNUNET_CONTAINER_DLL_insert (attrs->list_head,
325                                  attrs->list_tail,
326                                  le);
327     attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (le->claim);
328     read_ptr += attr_len;
329   }
330   return attrs;
331 }
332
333 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList*
334 GNUNET_IDENTITY_ATTRIBUTE_list_dup (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
335 {
336   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
337   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *result_le;
338   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *result;
339   size_t len;
340
341   result = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
342   for (le = attrs->list_head; NULL != le; le = le->next)
343   {
344     result_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
345     len = sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim) + le->claim->data_size;
346     result_le->claim = GNUNET_malloc (len);
347     GNUNET_memcpy (result_le->claim,
348                    le->claim,
349                    len);
350     result_le->claim->name = (const char*)&result_le->claim[1];
351     GNUNET_CONTAINER_DLL_insert (result->list_head,
352                                  result->list_tail,
353                                  result_le);
354   }
355   return result;
356 }
357
358
359 void
360 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
361 {
362   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
363   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *tmp_le;
364
365   for (le = attrs->list_head; NULL != le;)
366   {
367     GNUNET_free (le->claim);
368     tmp_le = le;
369     le = le->next;
370     GNUNET_free (tmp_le);
371   }
372   GNUNET_free (attrs);
373
374 }
375
376 size_t
377 GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
378 {
379   return sizeof (struct Attribute) 
380     + strlen (attr->name)
381     + attr->data_size;
382 }
383
384 size_t
385 GNUNET_IDENTITY_ATTRIBUTE_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
386                      char *result)
387 {
388   size_t data_len_ser;
389   size_t name_len;
390   struct Attribute *attr_ser;
391   char* write_ptr;
392
393   attr_ser = (struct Attribute*)result;
394   attr_ser->attribute_type = htons (attr->type);
395   attr_ser->attribute_version = htonl (attr->version);
396   name_len = strlen (attr->name);
397   attr_ser->name_len = htons (name_len);
398   write_ptr = (char*)&attr_ser[1];
399   GNUNET_memcpy (write_ptr, attr->name, name_len);
400   write_ptr += name_len;
401   //TODO plugin-ize
402   //data_len_ser = plugin->serialize_attribute_value (attr,
403   //                                                  &attr_ser[1]);
404   data_len_ser = attr->data_size;
405   GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
406   attr_ser->data_size = htons (data_len_ser);
407
408   return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
409 }
410
411 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
412 GNUNET_IDENTITY_ATTRIBUTE_deserialize (const char* data,
413                        size_t data_size)
414 {
415   struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
416   struct Attribute *attr_ser;
417   size_t data_len;
418   size_t name_len;
419   char* write_ptr;
420
421   if (data_size < sizeof (struct Attribute))
422     return NULL;
423
424   attr_ser = (struct Attribute*)data;
425   data_len = ntohs (attr_ser->data_size);
426   name_len = ntohs (attr_ser->name_len);
427   attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim)
428                         + data_len + name_len + 1);
429   attr->type = ntohs (attr_ser->attribute_type);
430   attr->version = ntohl (attr_ser->attribute_version);
431   attr->data_size = ntohs (attr_ser->data_size);
432
433   write_ptr =  (char*)&attr[1];
434   GNUNET_memcpy (write_ptr,
435                  &attr_ser[1],
436                  name_len);
437   write_ptr[name_len] = '\0';
438   attr->name = write_ptr;
439
440   write_ptr += name_len + 1;
441   GNUNET_memcpy (write_ptr,
442                  (char*)&attr_ser[1] + name_len,
443                  attr->data_size);
444   attr->data = write_ptr;
445   return attr;
446
447 }
448
449 /* end of identity_attribute.c */