reclaim_attribute.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. /*
  2. This file is part of GNUnet
  3. Copyright (C) 2010-2015 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file reclaim-attribute/reclaim_attribute.c
  18. * @brief helper library to manage identity attributes
  19. * @author Martin Schanzenbach
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_reclaim_attribute_plugin.h"
  24. #include "reclaim_attribute.h"
  25. /**
  26. * Handle for a plugin
  27. */
  28. struct Plugin
  29. {
  30. /**
  31. * Name of the plugin
  32. */
  33. char *library_name;
  34. /**
  35. * Plugin API
  36. */
  37. struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api;
  38. };
  39. /**
  40. * Plugins
  41. */
  42. static struct Plugin **attr_plugins;
  43. /**
  44. * Number of plugins
  45. */
  46. static unsigned int num_plugins;
  47. /**
  48. * Init canary
  49. */
  50. static int initialized;
  51. /**
  52. * Add a plugin
  53. *
  54. * @param cls closure
  55. * @param library_name name of the API library
  56. * @param lib_ret the plugin API pointer
  57. */
  58. static void
  59. add_plugin (void *cls, const char *library_name, void *lib_ret)
  60. {
  61. struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api = lib_ret;
  62. struct Plugin *plugin;
  63. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  64. "Loading attribute plugin `%s'\n",
  65. library_name);
  66. plugin = GNUNET_new (struct Plugin);
  67. plugin->api = api;
  68. plugin->library_name = GNUNET_strdup (library_name);
  69. GNUNET_array_append (attr_plugins, num_plugins, plugin);
  70. }
  71. /**
  72. * Load plugins
  73. */
  74. static void
  75. init ()
  76. {
  77. if (GNUNET_YES == initialized)
  78. return;
  79. initialized = GNUNET_YES;
  80. GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_attribute_",
  81. NULL,
  82. &add_plugin,
  83. NULL);
  84. }
  85. /**
  86. * Convert a type name to the corresponding number
  87. *
  88. * @param typename name to convert
  89. * @return corresponding number, UINT32_MAX on error
  90. */
  91. uint32_t
  92. GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (const char *typename)
  93. {
  94. unsigned int i;
  95. struct Plugin *plugin;
  96. uint32_t ret;
  97. init ();
  98. for (i = 0; i < num_plugins; i++)
  99. {
  100. plugin = attr_plugins[i];
  101. if (UINT32_MAX !=
  102. (ret = plugin->api->typename_to_number (plugin->api->cls, typename)))
  103. return ret;
  104. }
  105. return UINT32_MAX;
  106. }
  107. /**
  108. * Convert a type number to the corresponding type string
  109. *
  110. * @param type number of a type
  111. * @return corresponding typestring, NULL on error
  112. */
  113. const char *
  114. GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (uint32_t type)
  115. {
  116. unsigned int i;
  117. struct Plugin *plugin;
  118. const char *ret;
  119. init ();
  120. for (i = 0; i < num_plugins; i++)
  121. {
  122. plugin = attr_plugins[i];
  123. if (NULL !=
  124. (ret = plugin->api->number_to_typename (plugin->api->cls, type)))
  125. return ret;
  126. }
  127. return NULL;
  128. }
  129. /**
  130. * Convert human-readable version of a 'claim' of an attribute to the binary
  131. * representation
  132. *
  133. * @param type type of the claim
  134. * @param s human-readable string
  135. * @param data set to value in binary encoding (will be allocated)
  136. * @param data_size set to number of bytes in @a data
  137. * @return #GNUNET_OK on success
  138. */
  139. int
  140. GNUNET_RECLAIM_ATTRIBUTE_string_to_value (uint32_t type,
  141. const char *s,
  142. void **data,
  143. size_t *data_size)
  144. {
  145. unsigned int i;
  146. struct Plugin *plugin;
  147. init ();
  148. for (i = 0; i < num_plugins; i++)
  149. {
  150. plugin = attr_plugins[i];
  151. if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
  152. type,
  153. s,
  154. data,
  155. data_size))
  156. return GNUNET_OK;
  157. }
  158. return GNUNET_SYSERR;
  159. }
  160. /**
  161. * Convert the 'claim' of an attribute to a string
  162. *
  163. * @param type the type of attribute
  164. * @param data claim in binary encoding
  165. * @param data_size number of bytes in @a data
  166. * @return NULL on error, otherwise human-readable representation of the claim
  167. */
  168. char *
  169. GNUNET_RECLAIM_ATTRIBUTE_value_to_string (uint32_t type,
  170. const void *data,
  171. size_t data_size)
  172. {
  173. unsigned int i;
  174. struct Plugin *plugin;
  175. char *ret;
  176. init ();
  177. for (i = 0; i < num_plugins; i++)
  178. {
  179. plugin = attr_plugins[i];
  180. if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
  181. type,
  182. data,
  183. data_size)))
  184. return ret;
  185. }
  186. return NULL;
  187. }
  188. /**
  189. * Create a new attribute.
  190. *
  191. * @param attr_name the attribute name
  192. * @param type the attribute type
  193. * @param data the attribute value
  194. * @param data_size the attribute value size
  195. * @return the new attribute
  196. */
  197. struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
  198. GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char *attr_name,
  199. uint32_t type,
  200. const void *data,
  201. size_t data_size)
  202. {
  203. struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
  204. char *write_ptr;
  205. char *attr_name_tmp = GNUNET_strdup (attr_name);
  206. GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
  207. attr = GNUNET_malloc (sizeof (struct GNUNET_RECLAIM_ATTRIBUTE_Claim) +
  208. strlen (attr_name_tmp) + 1 + data_size);
  209. attr->type = type;
  210. attr->data_size = data_size;
  211. attr->version = 0;
  212. write_ptr = (char *) &attr[1];
  213. GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
  214. attr->name = write_ptr;
  215. write_ptr += strlen (attr->name) + 1;
  216. GNUNET_memcpy (write_ptr, data, data_size);
  217. attr->data = write_ptr;
  218. GNUNET_free (attr_name_tmp);
  219. return attr;
  220. }
  221. /**
  222. * Add a new attribute to a claim list
  223. *
  224. * @param attr_name the name of the new attribute claim
  225. * @param type the type of the claim
  226. * @param data claim payload
  227. * @param data_size claim payload size
  228. */
  229. void
  230. GNUNET_RECLAIM_ATTRIBUTE_list_add (
  231. struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *claim_list,
  232. const char *attr_name,
  233. uint32_t type,
  234. const void *data,
  235. size_t data_size)
  236. {
  237. struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
  238. le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
  239. le->claim =
  240. GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name, type, data, data_size);
  241. GNUNET_CONTAINER_DLL_insert (claim_list->list_head,
  242. claim_list->list_tail,
  243. le);
  244. }
  245. /**
  246. * Get required size for serialization buffer
  247. *
  248. * @param attrs the attribute list to serialize
  249. * @return the required buffer size
  250. */
  251. size_t
  252. GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (
  253. const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
  254. {
  255. struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
  256. size_t len = 0;
  257. for (le = attrs->list_head; NULL != le; le = le->next)
  258. len += GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
  259. return len;
  260. }
  261. /**
  262. * Serialize an attribute list
  263. *
  264. * @param attrs the attribute list to serialize
  265. * @param result the serialized attribute
  266. * @return length of serialized data
  267. */
  268. size_t
  269. GNUNET_RECLAIM_ATTRIBUTE_list_serialize (
  270. const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
  271. char *result)
  272. {
  273. struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
  274. size_t len;
  275. size_t total_len;
  276. char *write_ptr;
  277. write_ptr = result;
  278. total_len = 0;
  279. for (le = attrs->list_head; NULL != le; le = le->next)
  280. {
  281. len = GNUNET_RECLAIM_ATTRIBUTE_serialize (le->claim, write_ptr);
  282. total_len += len;
  283. write_ptr += len;
  284. }
  285. return total_len;
  286. }
  287. /**
  288. * Deserialize an attribute list
  289. *
  290. * @param data the serialized attribute list
  291. * @param data_size the length of the serialized data
  292. * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
  293. */
  294. struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
  295. GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (const char *data, size_t data_size)
  296. {
  297. struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
  298. struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
  299. size_t attr_len;
  300. const char *read_ptr;
  301. if (data_size < sizeof (struct Attribute))
  302. return NULL;
  303. attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
  304. read_ptr = data;
  305. while (((data + data_size) - read_ptr) >= sizeof (struct Attribute))
  306. {
  307. le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
  308. le->claim =
  309. GNUNET_RECLAIM_ATTRIBUTE_deserialize (read_ptr,
  310. data_size - (read_ptr - data));
  311. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  312. "Deserialized attribute %s\n",
  313. le->claim->name);
  314. GNUNET_CONTAINER_DLL_insert (attrs->list_head, attrs->list_tail, le);
  315. attr_len = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
  316. read_ptr += attr_len;
  317. }
  318. return attrs;
  319. }
  320. /**
  321. * Make a (deep) copy of a claim list
  322. * @param attrs claim list to copy
  323. * @return copied claim list
  324. */
  325. struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
  326. GNUNET_RECLAIM_ATTRIBUTE_list_dup (
  327. const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
  328. {
  329. struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
  330. struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *result_le;
  331. struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *result;
  332. result = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
  333. for (le = attrs->list_head; NULL != le; le = le->next)
  334. {
  335. result_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
  336. result_le->claim =
  337. GNUNET_RECLAIM_ATTRIBUTE_claim_new (le->claim->name,
  338. le->claim->type,
  339. le->claim->data,
  340. le->claim->data_size);
  341. result_le->claim->version = le->claim->version;
  342. result_le->claim->id = le->claim->id;
  343. GNUNET_CONTAINER_DLL_insert (result->list_head,
  344. result->list_tail,
  345. result_le);
  346. }
  347. return result;
  348. }
  349. /**
  350. * Destroy claim list
  351. *
  352. * @param attrs list to destroy
  353. */
  354. void
  355. GNUNET_RECLAIM_ATTRIBUTE_list_destroy (
  356. struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
  357. {
  358. struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
  359. struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *tmp_le;
  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. * Get required size for serialization buffer
  371. *
  372. * @param attr the attribute to serialize
  373. * @return the required buffer size
  374. */
  375. size_t
  376. GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (
  377. const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
  378. {
  379. return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
  380. }
  381. /**
  382. * Serialize an attribute
  383. *
  384. * @param attr the attribute to serialize
  385. * @param result the serialized attribute
  386. * @return length of serialized data
  387. */
  388. size_t
  389. GNUNET_RECLAIM_ATTRIBUTE_serialize (
  390. const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
  391. char *result)
  392. {
  393. size_t data_len_ser;
  394. size_t name_len;
  395. struct Attribute *attr_ser;
  396. char *write_ptr;
  397. attr_ser = (struct Attribute *) result;
  398. attr_ser->attribute_type = htons (attr->type);
  399. attr_ser->attribute_version = htonl (attr->version);
  400. attr_ser->attribute_id = GNUNET_htonll (attr->id);
  401. name_len = strlen (attr->name);
  402. attr_ser->name_len = htons (name_len);
  403. write_ptr = (char *) &attr_ser[1];
  404. GNUNET_memcpy (write_ptr, attr->name, name_len);
  405. write_ptr += name_len;
  406. // TODO plugin-ize
  407. // data_len_ser = plugin->serialize_attribute_value (attr,
  408. // &attr_ser[1]);
  409. data_len_ser = attr->data_size;
  410. GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
  411. attr_ser->data_size = htons (data_len_ser);
  412. return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
  413. }
  414. /**
  415. * Deserialize an attribute
  416. *
  417. * @param data the serialized attribute
  418. * @param data_size the length of the serialized data
  419. *
  420. * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
  421. */
  422. struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
  423. GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char *data, size_t data_size)
  424. {
  425. struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
  426. struct Attribute *attr_ser;
  427. size_t data_len;
  428. size_t name_len;
  429. char *write_ptr;
  430. if (data_size < sizeof (struct Attribute))
  431. return NULL;
  432. attr_ser = (struct Attribute *) data;
  433. data_len = ntohs (attr_ser->data_size);
  434. name_len = ntohs (attr_ser->name_len);
  435. if (data_size < sizeof (struct Attribute) + data_len + name_len)
  436. {
  437. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  438. "Buffer too small to deserialize\n");
  439. return NULL;
  440. }
  441. attr = GNUNET_malloc (sizeof (struct GNUNET_RECLAIM_ATTRIBUTE_Claim) +
  442. data_len + name_len + 1);
  443. attr->type = ntohs (attr_ser->attribute_type);
  444. attr->version = ntohl (attr_ser->attribute_version);
  445. attr->id = GNUNET_ntohll (attr_ser->attribute_id);
  446. attr->data_size = data_len;
  447. write_ptr = (char *) &attr[1];
  448. GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
  449. write_ptr[name_len] = '\0';
  450. attr->name = write_ptr;
  451. write_ptr += name_len + 1;
  452. GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, attr->data_size);
  453. attr->data = write_ptr;
  454. return attr;
  455. }
  456. /* end of reclaim_attribute.c */