reclaim_attribute.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  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_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_AttributePluginFunctions *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_AttributePluginFunctions *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_in_context (GNUNET_OS_project_data_default (),
  81. "libgnunet_plugin_reclaim_attribute_",
  82. NULL,
  83. &add_plugin,
  84. NULL);
  85. }
  86. /**
  87. * Dual function to #init().
  88. */
  89. void __attribute__ ((destructor))
  90. RECLAIM_ATTRIBUTE_fini ()
  91. {
  92. struct Plugin *plugin;
  93. const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
  94. const struct GNUNET_OS_ProjectData *dpd = GNUNET_OS_project_data_default ();
  95. if (pd != dpd)
  96. GNUNET_OS_init (dpd);
  97. for (unsigned int i = 0; i < num_plugins; i++)
  98. {
  99. plugin = attr_plugins[i];
  100. GNUNET_break (NULL ==
  101. GNUNET_PLUGIN_unload (plugin->library_name,
  102. plugin->api));
  103. GNUNET_free (plugin->library_name);
  104. GNUNET_free (plugin);
  105. }
  106. GNUNET_free (attr_plugins);
  107. if (pd != dpd)
  108. GNUNET_OS_init (pd);
  109. attr_plugins = NULL;
  110. }
  111. /**
  112. * Convert a type name to the corresponding number
  113. *
  114. * @param typename name to convert
  115. * @return corresponding number, UINT32_MAX on error
  116. */
  117. uint32_t
  118. GNUNET_RECLAIM_attribute_typename_to_number (const char *typename)
  119. {
  120. unsigned int i;
  121. struct Plugin *plugin;
  122. uint32_t ret;
  123. init ();
  124. for (i = 0; i < num_plugins; i++)
  125. {
  126. plugin = attr_plugins[i];
  127. if (UINT32_MAX !=
  128. (ret = plugin->api->typename_to_number (plugin->api->cls, typename)))
  129. return ret;
  130. }
  131. return UINT32_MAX;
  132. }
  133. /**
  134. * Convert a type number to the corresponding type string
  135. *
  136. * @param type number of a type
  137. * @return corresponding typestring, NULL on error
  138. */
  139. const char *
  140. GNUNET_RECLAIM_attribute_number_to_typename (uint32_t type)
  141. {
  142. unsigned int i;
  143. struct Plugin *plugin;
  144. const char *ret;
  145. init ();
  146. for (i = 0; i < num_plugins; i++)
  147. {
  148. plugin = attr_plugins[i];
  149. if (NULL !=
  150. (ret = plugin->api->number_to_typename (plugin->api->cls, type)))
  151. return ret;
  152. }
  153. return NULL;
  154. }
  155. /**
  156. * Convert human-readable version of a 'claim' of an attribute to the binary
  157. * representation
  158. *
  159. * @param type type of the claim
  160. * @param s human-readable string
  161. * @param data set to value in binary encoding (will be allocated)
  162. * @param data_size set to number of bytes in @a data
  163. * @return #GNUNET_OK on success
  164. */
  165. int
  166. GNUNET_RECLAIM_attribute_string_to_value (uint32_t type,
  167. const char *s,
  168. void **data,
  169. size_t *data_size)
  170. {
  171. unsigned int i;
  172. struct Plugin *plugin;
  173. init ();
  174. for (i = 0; i < num_plugins; i++)
  175. {
  176. plugin = attr_plugins[i];
  177. if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
  178. type,
  179. s,
  180. data,
  181. data_size))
  182. return GNUNET_OK;
  183. }
  184. return GNUNET_SYSERR;
  185. }
  186. /**
  187. * Convert the 'claim' of an attribute to a string
  188. *
  189. * @param type the type of attribute
  190. * @param data claim in binary encoding
  191. * @param data_size number of bytes in @a data
  192. * @return NULL on error, otherwise human-readable representation of the claim
  193. */
  194. char *
  195. GNUNET_RECLAIM_attribute_value_to_string (uint32_t type,
  196. const void *data,
  197. size_t data_size)
  198. {
  199. unsigned int i;
  200. struct Plugin *plugin;
  201. char *ret;
  202. init ();
  203. for (i = 0; i < num_plugins; i++)
  204. {
  205. plugin = attr_plugins[i];
  206. if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
  207. type,
  208. data,
  209. data_size)))
  210. return ret;
  211. }
  212. return NULL;
  213. }
  214. /**
  215. * Create a new attribute.
  216. *
  217. * @param attr_name the attribute name
  218. * @param credential credential ID of the attribute (maybe NULL)
  219. * @param type the attribute type
  220. * @param data the attribute value
  221. * @param data_size the attribute value size
  222. * @return the new attribute
  223. */
  224. struct GNUNET_RECLAIM_Attribute *
  225. GNUNET_RECLAIM_attribute_new (const char *attr_name,
  226. const struct
  227. GNUNET_RECLAIM_Identifier *credential,
  228. uint32_t type,
  229. const void *data,
  230. size_t data_size)
  231. {
  232. struct GNUNET_RECLAIM_Attribute *attr;
  233. char *write_ptr;
  234. char *attr_name_tmp = GNUNET_strdup (attr_name);
  235. GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
  236. attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute)
  237. + strlen (attr_name_tmp) + 1 + data_size);
  238. if (NULL != credential)
  239. attr->credential = *credential;
  240. attr->type = type;
  241. attr->data_size = data_size;
  242. attr->flag = 0;
  243. write_ptr = (char *) &attr[1];
  244. GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
  245. attr->name = write_ptr;
  246. write_ptr += strlen (attr->name) + 1;
  247. GNUNET_memcpy (write_ptr, data, data_size);
  248. attr->data = write_ptr;
  249. GNUNET_free (attr_name_tmp);
  250. return attr;
  251. }
  252. /**
  253. * Add a new attribute to a claim list
  254. *
  255. * @param attr_name the name of the new attribute claim
  256. * @param type the type of the claim
  257. * @param data claim payload
  258. * @param data_size claim payload size
  259. */
  260. void
  261. GNUNET_RECLAIM_attribute_list_add (
  262. struct GNUNET_RECLAIM_AttributeList *al,
  263. const char *attr_name,
  264. const struct GNUNET_RECLAIM_Identifier *credential,
  265. uint32_t type,
  266. const void *data,
  267. size_t data_size)
  268. {
  269. struct GNUNET_RECLAIM_AttributeListEntry *ale;
  270. ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
  271. ale->attribute =
  272. GNUNET_RECLAIM_attribute_new (attr_name, credential,
  273. type, data, data_size);
  274. GNUNET_CONTAINER_DLL_insert (al->list_head,
  275. al->list_tail,
  276. ale);
  277. }
  278. /**
  279. * Get required size for serialization buffer
  280. *
  281. * @param attrs the attribute list to serialize
  282. * @return the required buffer size
  283. */
  284. size_t
  285. GNUNET_RECLAIM_attribute_list_serialize_get_size (
  286. const struct GNUNET_RECLAIM_AttributeList *al)
  287. {
  288. struct GNUNET_RECLAIM_AttributeListEntry *ale;
  289. size_t len = 0;
  290. for (ale = al->list_head; NULL != ale; ale = ale->next)
  291. {
  292. GNUNET_assert (NULL != ale->attribute);
  293. len += GNUNET_RECLAIM_attribute_serialize_get_size (ale->attribute);
  294. }
  295. return len;
  296. }
  297. /**
  298. * Serialize an attribute list
  299. *
  300. * @param attrs the attribute list to serialize
  301. * @param result the serialized attribute
  302. * @return length of serialized data
  303. */
  304. size_t
  305. GNUNET_RECLAIM_attribute_list_serialize (
  306. const struct GNUNET_RECLAIM_AttributeList *al,
  307. char *result)
  308. {
  309. struct GNUNET_RECLAIM_AttributeListEntry *ale;
  310. size_t len;
  311. size_t total_len;
  312. char *write_ptr;
  313. write_ptr = result;
  314. total_len = 0;
  315. for (ale = al->list_head; NULL != ale; ale = ale->next)
  316. {
  317. GNUNET_assert (NULL != ale->attribute);
  318. len = GNUNET_RECLAIM_attribute_serialize (ale->attribute, write_ptr);
  319. total_len += len;
  320. write_ptr += len;
  321. }
  322. return total_len;
  323. }
  324. /**
  325. * Deserialize an attribute list
  326. *
  327. * @param data the serialized attribute list
  328. * @param data_size the length of the serialized data
  329. * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
  330. */
  331. struct GNUNET_RECLAIM_AttributeList *
  332. GNUNET_RECLAIM_attribute_list_deserialize (const char *data, size_t data_size)
  333. {
  334. struct GNUNET_RECLAIM_AttributeList *al;
  335. struct GNUNET_RECLAIM_AttributeListEntry *ale;
  336. size_t attr_len;
  337. const char *read_ptr;
  338. size_t left = data_size;
  339. al = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
  340. if (data_size < sizeof(struct Attribute))
  341. return al;
  342. read_ptr = data;
  343. while (left >= sizeof(struct Attribute))
  344. {
  345. ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
  346. attr_len =
  347. GNUNET_RECLAIM_attribute_deserialize (read_ptr,
  348. left,
  349. &ale->attribute);
  350. if (-1 == attr_len)
  351. {
  352. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  353. "Failed to deserialize malformed attribute.\n");
  354. GNUNET_free (ale);
  355. return al;
  356. }
  357. left -= attr_len;
  358. GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
  359. read_ptr += attr_len;
  360. }
  361. return al;
  362. }
  363. /**
  364. * Make a (deep) copy of a claim list
  365. * @param attrs claim list to copy
  366. * @return copied claim list
  367. */
  368. struct GNUNET_RECLAIM_AttributeList *
  369. GNUNET_RECLAIM_attribute_list_dup (
  370. const struct GNUNET_RECLAIM_AttributeList *al)
  371. {
  372. struct GNUNET_RECLAIM_AttributeListEntry *ale;
  373. struct GNUNET_RECLAIM_AttributeListEntry *result_ale;
  374. struct GNUNET_RECLAIM_AttributeList *result;
  375. result = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
  376. for (ale = al->list_head; NULL != ale; ale = ale->next)
  377. {
  378. result_ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
  379. GNUNET_assert (NULL != ale->attribute);
  380. {
  381. result_ale->attribute =
  382. GNUNET_RECLAIM_attribute_new (ale->attribute->name,
  383. &ale->attribute->credential,
  384. ale->attribute->type,
  385. ale->attribute->data,
  386. ale->attribute->data_size);
  387. result_ale->attribute->id = ale->attribute->id;
  388. result_ale->attribute->flag = ale->attribute->flag;
  389. }
  390. GNUNET_CONTAINER_DLL_insert (result->list_head,
  391. result->list_tail,
  392. result_ale);
  393. }
  394. return result;
  395. }
  396. /**
  397. * Destroy claim list
  398. *
  399. * @param attrs list to destroy
  400. */
  401. void
  402. GNUNET_RECLAIM_attribute_list_destroy (
  403. struct GNUNET_RECLAIM_AttributeList *al)
  404. {
  405. struct GNUNET_RECLAIM_AttributeListEntry *ale;
  406. struct GNUNET_RECLAIM_AttributeListEntry *tmp_ale;
  407. for (ale = al->list_head; NULL != ale;)
  408. {
  409. if (NULL != ale->attribute)
  410. GNUNET_free (ale->attribute);
  411. tmp_ale = ale;
  412. ale = ale->next;
  413. GNUNET_free (tmp_ale);
  414. }
  415. GNUNET_free (al);
  416. }
  417. /**
  418. * Get required size for serialization buffer
  419. *
  420. * @param attr the attribute to serialize
  421. * @return the required buffer size
  422. */
  423. size_t
  424. GNUNET_RECLAIM_attribute_serialize_get_size (
  425. const struct GNUNET_RECLAIM_Attribute *attr)
  426. {
  427. return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
  428. }
  429. /**
  430. * Serialize an attribute
  431. *
  432. * @param attr the attribute to serialize
  433. * @param result the serialized attribute
  434. * @return length of serialized data
  435. */
  436. size_t
  437. GNUNET_RECLAIM_attribute_serialize (
  438. const struct GNUNET_RECLAIM_Attribute *attr,
  439. char *result)
  440. {
  441. size_t data_len_ser;
  442. size_t name_len;
  443. struct Attribute *attr_ser;
  444. char *write_ptr;
  445. attr_ser = (struct Attribute *) result;
  446. attr_ser->attribute_type = htons (attr->type);
  447. attr_ser->attribute_flag = htonl (attr->flag);
  448. attr_ser->attribute_id = attr->id;
  449. attr_ser->credential_id = attr->credential;
  450. name_len = strlen (attr->name);
  451. attr_ser->name_len = htons (name_len);
  452. write_ptr = (char *) &attr_ser[1];
  453. GNUNET_memcpy (write_ptr, attr->name, name_len);
  454. write_ptr += name_len;
  455. // TODO plugin-ize
  456. // data_len_ser = plugin->serialize_attribute_value (attr,
  457. // &attr_ser[1]);
  458. data_len_ser = attr->data_size;
  459. GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
  460. attr_ser->data_size = htons (data_len_ser);
  461. return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
  462. }
  463. /**
  464. * Deserialize an attribute
  465. *
  466. * @param data the serialized attribute
  467. * @param data_size the length of the serialized data
  468. *
  469. * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
  470. */
  471. ssize_t
  472. GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size,
  473. struct GNUNET_RECLAIM_Attribute **attr)
  474. {
  475. struct Attribute *attr_ser;
  476. struct GNUNET_RECLAIM_Attribute *attribute;
  477. size_t data_len;
  478. size_t name_len;
  479. char *write_ptr;
  480. if (data_size < sizeof(struct Attribute))
  481. return -1;
  482. attr_ser = (struct Attribute *) data;
  483. data_len = ntohs (attr_ser->data_size);
  484. name_len = ntohs (attr_ser->name_len);
  485. if (data_size < sizeof(struct Attribute) + data_len + name_len)
  486. {
  487. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  488. "Buffer too small to deserialize\n");
  489. return -1;
  490. }
  491. attribute = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute)
  492. + data_len + name_len + 1);
  493. attribute->type = ntohs (attr_ser->attribute_type);
  494. attribute->flag = ntohl (attr_ser->attribute_flag);
  495. attribute->id = attr_ser->attribute_id;
  496. attribute->credential = attr_ser->credential_id;
  497. attribute->data_size = data_len;
  498. write_ptr = (char *) &attribute[1];
  499. GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
  500. write_ptr[name_len] = '\0';
  501. attribute->name = write_ptr;
  502. write_ptr += name_len + 1;
  503. GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len,
  504. attribute->data_size);
  505. *attr = attribute;
  506. attribute->data = write_ptr;
  507. return sizeof(struct Attribute) + data_len + name_len;
  508. }
  509. /* end of reclaim_attribute.c */