2 This file is part of GNUnet
3 Copyright (C) 2010-2015 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file reclaim-attribute/reclaim_attribute.c
23 * @brief helper library to manage identity attributes
24 * @author Martin Schanzenbach
27 #include "gnunet_util_lib.h"
28 #include "gnunet_reclaim_plugin.h"
29 #include "reclaim_attribute.h"
45 struct GNUNET_RECLAIM_AttributePluginFunctions *api;
52 static struct Plugin **attr_plugins;
58 static unsigned int num_plugins;
64 static int initialized;
71 * @param library_name name of the API library
72 * @param lib_ret the plugin API pointer
75 add_plugin (void *cls, const char *library_name, void *lib_ret)
77 struct GNUNET_RECLAIM_AttributePluginFunctions *api = lib_ret;
78 struct Plugin *plugin;
80 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
81 "Loading attribute plugin `%s'\n",
83 plugin = GNUNET_new (struct Plugin);
85 plugin->library_name = GNUNET_strdup (library_name);
86 GNUNET_array_append (attr_plugins, num_plugins, plugin);
96 if (GNUNET_YES == initialized)
98 initialized = GNUNET_YES;
99 GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_attribute_",
107 * Convert a type name to the corresponding number
109 * @param typename name to convert
110 * @return corresponding number, UINT32_MAX on error
113 GNUNET_RECLAIM_attribute_typename_to_number (const char *typename)
116 struct Plugin *plugin;
120 for (i = 0; i < num_plugins; i++)
122 plugin = attr_plugins[i];
124 (ret = plugin->api->typename_to_number (plugin->api->cls, typename)))
132 * Convert a type number to the corresponding type string
134 * @param type number of a type
135 * @return corresponding typestring, NULL on error
138 GNUNET_RECLAIM_attribute_number_to_typename (uint32_t type)
141 struct Plugin *plugin;
145 for (i = 0; i < num_plugins; i++)
147 plugin = attr_plugins[i];
149 (ret = plugin->api->number_to_typename (plugin->api->cls, type)))
157 * Convert human-readable version of a 'claim' of an attribute to the binary
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
167 GNUNET_RECLAIM_attribute_string_to_value (uint32_t type,
173 struct Plugin *plugin;
176 for (i = 0; i < num_plugins; i++)
178 plugin = attr_plugins[i];
179 if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
186 return GNUNET_SYSERR;
191 * Convert the 'claim' of an attribute to a string
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
199 GNUNET_RECLAIM_attribute_value_to_string (uint32_t type,
204 struct Plugin *plugin;
208 for (i = 0; i < num_plugins; i++)
210 plugin = attr_plugins[i];
211 if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
222 * Create a new attribute.
224 * @param attr_name the attribute name
225 * @param attestation attestation ID of the attribute (maybe NULL)
226 * @param type the attribute type
227 * @param data the attribute value
228 * @param data_size the attribute value size
229 * @return the new attribute
231 struct GNUNET_RECLAIM_Attribute *
232 GNUNET_RECLAIM_attribute_new (const char *attr_name,
233 const struct GNUNET_RECLAIM_Identifier *attestation,
238 struct GNUNET_RECLAIM_Attribute *attr;
240 char *attr_name_tmp = GNUNET_strdup (attr_name);
242 GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
244 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute)
245 + strlen (attr_name_tmp) + 1 + data_size);
246 if (NULL != attestation)
247 attr->attestation = *attestation;
249 attr->data_size = data_size;
251 write_ptr = (char *) &attr[1];
252 GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
253 attr->name = write_ptr;
254 write_ptr += strlen (attr->name) + 1;
255 GNUNET_memcpy (write_ptr, data, data_size);
256 attr->data = write_ptr;
257 GNUNET_free (attr_name_tmp);
263 * Add a new attribute to a claim list
265 * @param attr_name the name of the new attribute claim
266 * @param type the type of the claim
267 * @param data claim payload
268 * @param data_size claim payload size
271 GNUNET_RECLAIM_attribute_list_add (
272 struct GNUNET_RECLAIM_AttributeList *al,
273 const char *attr_name,
274 const struct GNUNET_RECLAIM_Identifier *attestation,
279 struct GNUNET_RECLAIM_AttributeListEntry *ale;
281 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
283 GNUNET_RECLAIM_attribute_new (attr_name, attestation,
284 type, data, data_size);
285 GNUNET_CONTAINER_DLL_insert (al->list_head,
292 * Get required size for serialization buffer
294 * @param attrs the attribute list to serialize
295 * @return the required buffer size
298 GNUNET_RECLAIM_attribute_list_serialize_get_size (
299 const struct GNUNET_RECLAIM_AttributeList *al)
301 struct GNUNET_RECLAIM_AttributeListEntry *ale;
304 for (ale = al->list_head; NULL != ale; ale = ale->next)
306 GNUNET_assert (NULL != ale->attribute);
307 len += GNUNET_RECLAIM_attribute_serialize_get_size (ale->attribute);
308 len += sizeof(struct GNUNET_RECLAIM_AttributeListEntry);
315 * Serialize an attribute list
317 * @param attrs the attribute list to serialize
318 * @param result the serialized attribute
319 * @return length of serialized data
322 GNUNET_RECLAIM_attribute_list_serialize (
323 const struct GNUNET_RECLAIM_AttributeList *al,
326 struct GNUNET_RECLAIM_AttributeListEntry *ale;
332 for (ale = al->list_head; NULL != ale; ale = ale->next)
334 GNUNET_assert (NULL != ale->attribute);
335 len = GNUNET_RECLAIM_attribute_serialize (ale->attribute, write_ptr);
344 * Deserialize an attribute list
346 * @param data the serialized attribute list
347 * @param data_size the length of the serialized data
348 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
350 struct GNUNET_RECLAIM_AttributeList *
351 GNUNET_RECLAIM_attribute_list_deserialize (const char *data, size_t data_size)
353 struct GNUNET_RECLAIM_AttributeList *al;
354 struct GNUNET_RECLAIM_AttributeListEntry *ale;
356 const char *read_ptr;
358 al = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
359 if (data_size < sizeof(struct Attribute) + sizeof(struct
360 GNUNET_RECLAIM_AttributeListEntry))
363 while (((data + data_size) - read_ptr) >= sizeof(struct Attribute))
365 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
367 GNUNET_RECLAIM_attribute_deserialize (read_ptr,
368 data_size - (read_ptr - data));
369 GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
370 attr_len = GNUNET_RECLAIM_attribute_serialize_get_size (ale->attribute);
371 read_ptr += attr_len;
378 * Make a (deep) copy of a claim list
379 * @param attrs claim list to copy
380 * @return copied claim list
382 struct GNUNET_RECLAIM_AttributeList *
383 GNUNET_RECLAIM_attribute_list_dup (
384 const struct GNUNET_RECLAIM_AttributeList *al)
386 struct GNUNET_RECLAIM_AttributeListEntry *ale;
387 struct GNUNET_RECLAIM_AttributeListEntry *result_ale;
388 struct GNUNET_RECLAIM_AttributeList *result;
390 result = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
391 for (ale = al->list_head; NULL != ale; ale = ale->next)
393 result_ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
394 GNUNET_assert (NULL != ale->attribute);
396 result_ale->attribute =
397 GNUNET_RECLAIM_attribute_new (ale->attribute->name,
398 &ale->attribute->attestation,
399 ale->attribute->type,
400 ale->attribute->data,
401 ale->attribute->data_size);
403 result_ale->attribute->id = ale->attribute->id;
404 result_ale->attribute->flag = ale->attribute->flag;
406 GNUNET_CONTAINER_DLL_insert (result->list_head,
417 * @param attrs list to destroy
420 GNUNET_RECLAIM_attribute_list_destroy (
421 struct GNUNET_RECLAIM_AttributeList *al)
423 struct GNUNET_RECLAIM_AttributeListEntry *ale;
424 struct GNUNET_RECLAIM_AttributeListEntry *tmp_ale;
426 for (ale = al->list_head; NULL != ale;)
428 if (NULL != ale->attribute)
429 GNUNET_free (ale->attribute);
432 GNUNET_free (tmp_ale);
439 * Get required size for serialization buffer
441 * @param attr the attribute to serialize
442 * @return the required buffer size
445 GNUNET_RECLAIM_attribute_serialize_get_size (
446 const struct GNUNET_RECLAIM_Attribute *attr)
448 return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
453 * Serialize an attribute
455 * @param attr the attribute to serialize
456 * @param result the serialized attribute
457 * @return length of serialized data
460 GNUNET_RECLAIM_attribute_serialize (
461 const struct GNUNET_RECLAIM_Attribute *attr,
466 struct Attribute *attr_ser;
469 attr_ser = (struct Attribute *) result;
470 attr_ser->attribute_type = htons (attr->type);
471 attr_ser->attribute_flag = htonl (attr->flag);
472 attr_ser->attribute_id = attr->id;
473 name_len = strlen (attr->name);
474 attr_ser->name_len = htons (name_len);
475 write_ptr = (char *) &attr_ser[1];
476 GNUNET_memcpy (write_ptr, attr->name, name_len);
477 write_ptr += name_len;
479 // data_len_ser = plugin->serialize_attribute_value (attr,
481 data_len_ser = attr->data_size;
482 GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
483 attr_ser->data_size = htons (data_len_ser);
485 return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
490 * Deserialize an attribute
492 * @param data the serialized attribute
493 * @param data_size the length of the serialized data
495 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
497 struct GNUNET_RECLAIM_Attribute *
498 GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size)
500 struct GNUNET_RECLAIM_Attribute *attr;
501 struct Attribute *attr_ser;
506 if (data_size < sizeof(struct Attribute))
509 attr_ser = (struct Attribute *) data;
510 data_len = ntohs (attr_ser->data_size);
511 name_len = ntohs (attr_ser->name_len);
512 if (data_size < sizeof(struct Attribute) + data_len + name_len)
514 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
515 "Buffer too small to deserialize\n");
518 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute)
519 + data_len + name_len + 1);
520 attr->type = ntohs (attr_ser->attribute_type);
521 attr->flag = ntohl (attr_ser->attribute_flag);
522 attr->id = attr_ser->attribute_id;
523 attr->data_size = data_len;
525 write_ptr = (char *) &attr[1];
526 GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
527 write_ptr[name_len] = '\0';
528 attr->name = write_ptr;
530 write_ptr += name_len + 1;
531 GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, attr->data_size);
532 attr->data = write_ptr;
537 /* end of reclaim_attribute.c */