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