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_attribute_plugin.h"
29 #include "reclaim_attribute.h"
45 struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *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_ATTRIBUTE_PluginFunctions *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,
221 * Convert an attestation type name to the corresponding number
223 * @param typename name to convert
224 * @return corresponding number, UINT32_MAX on error
227 GNUNET_RECLAIM_ATTESTATION_typename_to_number (const char *typename)
230 struct Plugin *plugin;
233 for (i = 0; i < num_plugins; i++)
235 plugin = attr_plugins[i];
237 (ret = plugin->api->typename_to_number_attest (plugin->api->cls,
245 * Convert an attestation type number to the corresponding attestation type string
247 * @param type number of a type
248 * @return corresponding typestring, NULL on error
251 GNUNET_RECLAIM_ATTESTATION_number_to_typename (uint32_t type)
254 struct Plugin *plugin;
258 for (i = 0; i < num_plugins; i++)
260 plugin = attr_plugins[i];
262 (ret = plugin->api->number_to_typename_attest (plugin->api->cls, type)))
268 * Convert human-readable version of a 'claim' of an attestation to the binary
271 * @param type type of the claim
272 * @param s human-readable string
273 * @param data set to value in binary encoding (will be allocated)
274 * @param data_size set to number of bytes in @a data
275 * @return #GNUNET_OK on success
278 GNUNET_RECLAIM_ATTESTATION_string_to_value (uint32_t type,
284 struct Plugin *plugin;
287 for (i = 0; i < num_plugins; i++)
289 plugin = attr_plugins[i];
290 if (GNUNET_OK == plugin->api->string_to_value_attest (plugin->api->cls,
297 return GNUNET_SYSERR;
302 * Convert the 'claim' of an attestation to a string
304 * @param type the type of attestation
305 * @param data claim in binary encoding
306 * @param data_size number of bytes in @a data
307 * @return NULL on error, otherwise human-readable representation of the claim
310 GNUNET_RECLAIM_ATTESTATION_value_to_string (uint32_t type,
315 struct Plugin *plugin;
319 for (i = 0; i < num_plugins; i++)
321 plugin = attr_plugins[i];
322 if (NULL != (ret = plugin->api->value_to_string_attest (plugin->api->cls,
332 * Create a new attribute.
334 * @param attr_name the attribute name
335 * @param type the attribute type
336 * @param data the attribute value
337 * @param data_size the attribute value size
338 * @return the new attribute
340 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
341 GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char *attr_name,
346 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
348 char *attr_name_tmp = GNUNET_strdup (attr_name);
350 GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
352 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_Claim)
353 + strlen (attr_name_tmp) + 1 + data_size);
355 attr->data_size = data_size;
357 write_ptr = (char *) &attr[1];
358 GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
359 attr->name = write_ptr;
360 write_ptr += strlen (attr->name) + 1;
361 GNUNET_memcpy (write_ptr, data, data_size);
362 attr->data = write_ptr;
363 GNUNET_free (attr_name_tmp);
368 * Create a new attestation.
370 * @param attr_name the attestation name
371 * @param type the attestation type
372 * @param data the attestation value
373 * @param data_size the attestation value size
374 * @return the new attestation
376 struct GNUNET_RECLAIM_ATTESTATION_Claim *
377 GNUNET_RECLAIM_ATTESTATION_claim_new (const char *attr_name,
382 struct GNUNET_RECLAIM_ATTESTATION_Claim *attr;
384 char *attr_name_tmp = GNUNET_strdup (attr_name);
386 GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
388 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim)
389 + strlen (attr_name_tmp) + 1 + data_size);
391 attr->data_size = data_size;
393 write_ptr = (char *) &attr[1];
394 GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
395 attr->name = write_ptr;
396 write_ptr += strlen (attr->name) + 1;
397 GNUNET_memcpy (write_ptr, data, data_size);
398 attr->data = write_ptr;
399 GNUNET_free (attr_name_tmp);
404 * Create a new attestation reference.
406 * @param attr_name the referenced claim name
407 * @param ref_value the claim name in the attestation
408 * @return the new reference
410 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *
411 GNUNET_RECLAIM_ATTESTATION_reference_new (const char *attr_name,
412 const char *ref_value)
414 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
416 char *attr_name_tmp = GNUNET_strdup (attr_name);
417 char *ref_value_tmp = GNUNET_strdup (ref_value);
419 GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
420 GNUNET_STRINGS_utf8_tolower (ref_value, ref_value_tmp);
422 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_REFERENCE)
423 + strlen (attr_name_tmp) + strlen (ref_value_tmp) + 2);
425 write_ptr = (char *) &attr[1];
426 GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
427 attr->name = write_ptr;
429 write_ptr = (char *) &attr[1];
430 GNUNET_memcpy (write_ptr, ref_value_tmp, strlen (ref_value_tmp) + 1);
431 attr->reference_value = write_ptr;
433 GNUNET_free (attr_name_tmp);
434 GNUNET_free (ref_value_tmp);
439 * Add a new attribute to a claim list
441 * @param attr_name the name of the new attribute claim
442 * @param type the type of the claim
443 * @param data claim payload
444 * @param data_size claim payload size
447 GNUNET_RECLAIM_ATTRIBUTE_list_add (
448 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *claim_list,
449 const char *attr_name,
454 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
456 le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
458 GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name, type, data, data_size);
459 GNUNET_CONTAINER_DLL_insert (claim_list->list_head,
460 claim_list->list_tail,
466 * Get required size for serialization buffer
468 * @param attrs the attribute list to serialize
469 * @return the required buffer size
472 GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (
473 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
475 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
478 for (le = attrs->list_head; NULL != le; le = le->next)
479 len += GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
485 * Serialize an attribute list
487 * @param attrs the attribute list to serialize
488 * @param result the serialized attribute
489 * @return length of serialized data
492 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (
493 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
496 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
503 for (le = attrs->list_head; NULL != le; le = le->next)
505 len = GNUNET_RECLAIM_ATTRIBUTE_serialize (le->claim, write_ptr);
514 * Deserialize an attribute list
516 * @param data the serialized attribute list
517 * @param data_size the length of the serialized data
518 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
520 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
521 GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (const char *data, size_t data_size)
523 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
524 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
526 const char *read_ptr;
528 if (data_size < sizeof(struct Attribute))
531 attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
533 while (((data + data_size) - read_ptr) >= sizeof(struct Attribute))
535 le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
537 GNUNET_RECLAIM_ATTRIBUTE_deserialize (read_ptr,
538 data_size - (read_ptr - data));
539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
540 "Deserialized attribute %s\n",
542 GNUNET_CONTAINER_DLL_insert (attrs->list_head, attrs->list_tail, le);
543 attr_len = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
544 read_ptr += attr_len;
551 * Make a (deep) copy of a claim list
552 * @param attrs claim list to copy
553 * @return copied claim list
555 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
556 GNUNET_RECLAIM_ATTRIBUTE_list_dup (
557 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
559 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
560 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *result_le;
561 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *result;
563 result = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
564 for (le = attrs->list_head; NULL != le; le = le->next)
566 result_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
568 GNUNET_RECLAIM_ATTRIBUTE_claim_new (le->claim->name,
571 le->claim->data_size);
572 result_le->claim->version = le->claim->version;
573 result_le->claim->id = le->claim->id;
574 GNUNET_CONTAINER_DLL_insert (result->list_head,
585 * @param attrs list to destroy
588 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (
589 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
591 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
592 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *tmp_le;
594 for (le = attrs->list_head; NULL != le;)
596 GNUNET_free (le->claim);
599 GNUNET_free (tmp_le);
606 * Get required size for serialization buffer
608 * @param attr the attribute to serialize
609 * @return the required buffer size
612 GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (
613 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
615 return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
620 * Serialize an attribute
622 * @param attr the attribute to serialize
623 * @param result the serialized attribute
624 * @return length of serialized data
627 GNUNET_RECLAIM_ATTRIBUTE_serialize (
628 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
633 struct Attribute *attr_ser;
636 attr_ser = (struct Attribute *) result;
637 attr_ser->attribute_type = htons (attr->type);
638 attr_ser->attribute_version = htonl (attr->version);
639 attr_ser->attribute_id = GNUNET_htonll (attr->id);
640 name_len = strlen (attr->name);
641 attr_ser->name_len = htons (name_len);
642 write_ptr = (char *) &attr_ser[1];
643 GNUNET_memcpy (write_ptr, attr->name, name_len);
644 write_ptr += name_len;
646 // data_len_ser = plugin->serialize_attribute_value (attr,
648 data_len_ser = attr->data_size;
649 GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
650 attr_ser->data_size = htons (data_len_ser);
652 return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
657 * Deserialize an attribute
659 * @param data the serialized attribute
660 * @param data_size the length of the serialized data
662 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
664 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
665 GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char *data, size_t data_size)
667 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
668 struct Attribute *attr_ser;
673 if (data_size < sizeof(struct Attribute))
676 attr_ser = (struct Attribute *) data;
677 data_len = ntohs (attr_ser->data_size);
678 name_len = ntohs (attr_ser->name_len);
679 if (data_size < sizeof(struct Attribute) + data_len + name_len)
681 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
682 "Buffer too small to deserialize\n");
685 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_Claim)
686 + data_len + name_len + 1);
687 attr->type = ntohs (attr_ser->attribute_type);
688 attr->version = ntohl (attr_ser->attribute_version);
689 attr->id = GNUNET_ntohll (attr_ser->attribute_id);
690 attr->data_size = data_len;
692 write_ptr = (char *) &attr[1];
693 GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
694 write_ptr[name_len] = '\0';
695 attr->name = write_ptr;
697 write_ptr += name_len + 1;
698 GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, attr->data_size);
699 attr->data = write_ptr;
705 * Get required size for serialization buffer
707 * @param attr the attestation to serialize
708 * @return the required buffer size
711 GNUNET_RECLAIM_ATTESTATION_serialize_get_size (
712 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr)
714 return sizeof(struct Attestation) + strlen (attr->name) + attr->data_size;
718 * Serialize an attestation
720 * @param attr the attestation to serialize
721 * @param result the serialized attestation
722 * @return length of serialized data
725 GNUNET_RECLAIM_ATTESTATION_serialize (
726 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr,
731 struct Attestation *attr_ser;
734 attr_ser = (struct Attestation *) result;
735 attr_ser->attestation_type = htons (attr->type);
736 attr_ser->attestation_version = htonl (attr->version);
737 attr_ser->attestation_id = GNUNET_htonll (attr->id);
738 name_len = strlen (attr->name);
739 attr_ser->name_len = htons (name_len);
740 write_ptr = (char *) &attr_ser[1];
741 GNUNET_memcpy (write_ptr, attr->name, name_len);
742 write_ptr += name_len;
744 // data_len_ser = plugin->serialize_attribute_value (attr,
746 data_len_ser = attr->data_size;
747 GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
748 attr_ser->data_size = htons (data_len_ser);
750 return sizeof(struct Attestation) + strlen (attr->name) + attr->data_size;
754 * Deserialize an attestation
756 * @param data the serialized attestation
757 * @param data_size the length of the serialized data
759 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
761 struct GNUNET_RECLAIM_ATTESTATION_Claim *
762 GNUNET_RECLAIM_ATTESTATION_deserialize (const char *data, size_t data_size)
764 struct GNUNET_RECLAIM_ATTESTATION_Claim *attr;
765 struct Attestation *attr_ser;
770 if (data_size < sizeof(struct Attestation))
773 attr_ser = (struct Attestation *) data;
774 data_len = ntohs (attr_ser->data_size);
775 name_len = ntohs (attr_ser->name_len);
776 if (data_size < sizeof(struct Attestation) + data_len + name_len)
778 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
779 "Buffer too small to deserialize\n");
782 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim)
783 + data_len + name_len + 1);
784 attr->type = ntohs (attr_ser->attestation_type);
785 attr->version = ntohl (attr_ser->attestation_version);
786 attr->id = GNUNET_ntohll (attr_ser->attestation_id);
787 attr->data_size = data_len;
789 write_ptr = (char *) &attr[1];
790 GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
791 write_ptr[name_len] = '\0';
792 attr->name = write_ptr;
794 write_ptr += name_len + 1;
795 GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, attr->data_size);
796 attr->data = write_ptr;
801 * Get required size for serialization buffer
803 * @param attr the reference to serialize
804 * @return the required buffer size
807 GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (
808 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr)
810 return sizeof(struct Attestation_Reference) + strlen (attr->name) + strlen (
811 attr->reference_value);
816 * Serialize a reference
818 * @param attr the reference to serialize
819 * @param result the serialized reference
820 * @return length of serialized data
823 GNUNET_RECLAIM_ATTESTATION_REF_serialize (
824 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr,
829 struct Attestation_Reference *attr_ser;
831 attr_ser = (struct Attestation_Reference *) result;
832 attr_ser->reference_id = GNUNET_htonll (attr->id);
833 attr_ser->attestation_id = GNUNET_htonll (attr->id_attest);
834 name_len = strlen (attr->name);
835 refval_len = strlen (attr->reference_value);
836 attr_ser->name_len = htons (name_len);
837 attr_ser->ref_value_len = htons (refval_len);
838 write_ptr = (char *) &attr_ser[1];
839 GNUNET_memcpy (write_ptr, attr->name, name_len);
840 write_ptr += name_len;
841 GNUNET_memcpy (write_ptr, attr->reference_value, refval_len);
843 return sizeof(struct Attestation_Reference) + strlen (attr->name) + strlen (
844 attr->reference_value);
849 * Deserialize a reference
851 * @param data the serialized reference
852 * @param data_size the length of the serialized data
854 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
856 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *
857 GNUNET_RECLAIM_ATTESTATION_REF_deserialize (const char *data, size_t data_size)
859 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
860 struct Attestation_Reference *attr_ser;
865 if (data_size < sizeof(struct Attestation_Reference))
867 attr_ser = (struct Attestation_Reference *) data;
868 name_len = ntohs (attr_ser->name_len);
869 refval_len = ntohs (attr_ser->ref_value_len);
870 if (data_size < sizeof(struct Attestation_Reference) + refval_len + name_len)
872 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
873 "Buffer too small to deserialize\n");
876 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_REFERENCE)
877 + refval_len + name_len + 2);
879 attr->id = GNUNET_ntohll (attr_ser->reference_id);
880 attr->id_attest = GNUNET_ntohll (attr_ser->attestation_id);
882 write_ptr = (char *) &attr[1];
883 GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
884 write_ptr[name_len] = '\0';
885 attr->name = write_ptr;
887 write_ptr += name_len + 1;
888 GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, refval_len);
889 write_ptr[refval_len] = '\0';
890 attr->reference_value = write_ptr;
893 /* end of reclaim_attribute.c */