a8aae6ced7593da8382436837fd1cedb80243ddc
[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-provider/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 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 attr_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 = attr_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 size_t
244 GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
245 {
246   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
247   size_t len = 0;
248   for (le = attrs->list_head; NULL != le; le = le->next)
249     len += GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (le->claim);
250   return len; 
251 }
252
253 size_t
254 GNUNET_IDENTITY_ATTRIBUTE_list_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
255                           char *result)
256 {
257   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
258   size_t len;
259   size_t total_len;
260   char* write_ptr;
261
262   write_ptr = result;
263   total_len = 0;
264   for (le = attrs->list_head; NULL != le; le = le->next)
265   {
266     len = GNUNET_IDENTITY_ATTRIBUTE_serialize (le->claim,
267                                write_ptr);
268     total_len += len;
269     write_ptr += len;
270   }
271   return total_len;
272 }
273
274 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *
275 GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (const char* data,
276                        size_t data_size)
277 {
278   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
279   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
280   size_t attr_len;
281   const char* read_ptr;
282
283   if (data_size < sizeof (struct Attribute))
284     return NULL;
285   
286   attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
287   read_ptr = data;
288   while (((data + data_size) - read_ptr) >= sizeof (struct Attribute))
289   {
290
291     le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
292     le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (read_ptr,
293                                            data_size - (read_ptr - data));
294     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
295                 "Deserialized attribute %s\n", le->claim->name);
296     GNUNET_CONTAINER_DLL_insert (attrs->list_head,
297                                  attrs->list_tail,
298                                  le);
299     attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (le->claim);
300     read_ptr += attr_len;
301   }
302   return attrs;
303 }
304
305 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList*
306 GNUNET_IDENTITY_ATTRIBUTE_list_dup (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
307 {
308   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
309   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *result_le;
310   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *result;
311   size_t len;
312
313   result = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
314   for (le = attrs->list_head; NULL != le; le = le->next)
315   {
316     result_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
317     len = sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim) + le->claim->data_size;
318     result_le->claim = GNUNET_malloc (len);
319     GNUNET_memcpy (result_le->claim,
320                    le->claim,
321                    len);
322     result_le->claim->name = (const char*)&result_le->claim[1];
323     GNUNET_CONTAINER_DLL_insert (result->list_head,
324                                  result->list_tail,
325                                  result_le);
326   }
327   return result;
328 }
329
330
331 void
332 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
333 {
334   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
335   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *tmp_le;
336
337   for (le = attrs->list_head; NULL != le;)
338   {
339     GNUNET_free (le->claim);
340     tmp_le = le;
341     le = le->next;
342     GNUNET_free (tmp_le);
343   }
344   GNUNET_free (attrs);
345
346 }
347
348 size_t
349 GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
350 {
351   return sizeof (struct Attribute) 
352     + strlen (attr->name)
353     + attr->data_size;
354 }
355
356 size_t
357 GNUNET_IDENTITY_ATTRIBUTE_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
358                      char *result)
359 {
360   size_t data_len_ser;
361   size_t name_len;
362   struct Attribute *attr_ser;
363   char* write_ptr;
364
365   attr_ser = (struct Attribute*)result;
366   attr_ser->attribute_type = htons (attr->type);
367   attr_ser->attribute_version = htonl (attr->version);
368   name_len = strlen (attr->name);
369   attr_ser->name_len = htons (name_len);
370   write_ptr = (char*)&attr_ser[1];
371   GNUNET_memcpy (write_ptr, attr->name, name_len);
372   write_ptr += name_len;
373   //TODO plugin-ize
374   //data_len_ser = plugin->serialize_attribute_value (attr,
375   //                                                  &attr_ser[1]);
376   data_len_ser = attr->data_size;
377   GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
378   attr_ser->data_size = htons (data_len_ser);
379
380   return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
381 }
382
383 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
384 GNUNET_IDENTITY_ATTRIBUTE_deserialize (const char* data,
385                        size_t data_size)
386 {
387   struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
388   struct Attribute *attr_ser;
389   size_t data_len;
390   size_t name_len;
391   char* write_ptr;
392
393   if (data_size < sizeof (struct Attribute))
394     return NULL;
395
396   attr_ser = (struct Attribute*)data;
397   data_len = ntohs (attr_ser->data_size);
398   name_len = ntohs (attr_ser->name_len);
399   attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim)
400                         + data_len + name_len + 1);
401   attr->type = ntohs (attr_ser->attribute_type);
402   attr->version = ntohl (attr_ser->attribute_version);
403   attr->data_size = ntohs (attr_ser->data_size);
404
405   write_ptr =  (char*)&attr[1];
406   GNUNET_memcpy (write_ptr,
407                  &attr_ser[1],
408                  name_len);
409   write_ptr[name_len] = '\0';
410   attr->name = write_ptr;
411
412   write_ptr += name_len + 1;
413   GNUNET_memcpy (write_ptr,
414                  (char*)&attr_ser[1] + name_len,
415                  attr->data_size);
416   attr->data = write_ptr;
417   return attr;
418
419 }
420
421 /* end of identity_attribute.c */