plugin_rest_reclaim.c 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2012-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. * @author Martin Schanzenbach
  18. * @author Philippe Buschmann
  19. * @file reclaim/plugin_rest_reclaim.c
  20. * @brief GNUnet reclaim REST plugin
  21. *
  22. */
  23. #include "platform.h"
  24. #include "microhttpd.h"
  25. #include <inttypes.h>
  26. #include <jansson.h>
  27. #include "gnunet_gns_service.h"
  28. #include "gnunet_gnsrecord_lib.h"
  29. #include "gnunet_identity_service.h"
  30. #include "gnunet_reclaim_lib.h"
  31. #include "gnunet_reclaim_service.h"
  32. #include "gnunet_rest_lib.h"
  33. #include "gnunet_rest_plugin.h"
  34. #include "gnunet_signatures.h"
  35. #include "json_reclaim.h"
  36. /**
  37. * REST root namespace
  38. */
  39. #define GNUNET_REST_API_NS_RECLAIM "/reclaim"
  40. /**
  41. * Attribute namespace
  42. */
  43. #define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/reclaim/attributes"
  44. /**
  45. * Credential namespace
  46. */
  47. #define GNUNET_REST_API_NS_RECLAIM_CREDENTIAL "/reclaim/credential"
  48. /**
  49. * Ticket namespace
  50. */
  51. #define GNUNET_REST_API_NS_IDENTITY_TICKETS "/reclaim/tickets"
  52. /**
  53. * Revoke namespace
  54. */
  55. #define GNUNET_REST_API_NS_IDENTITY_REVOKE "/reclaim/revoke"
  56. /**
  57. * Revoke namespace
  58. */
  59. #define GNUNET_REST_API_NS_IDENTITY_CONSUME "/reclaim/consume"
  60. /**
  61. * State while collecting all egos
  62. */
  63. #define ID_REST_STATE_INIT 0
  64. /**
  65. * Done collecting egos
  66. */
  67. #define ID_REST_STATE_POST_INIT 1
  68. /**
  69. * The configuration handle
  70. */
  71. const struct GNUNET_CONFIGURATION_Handle *cfg;
  72. /**
  73. * HTTP methods allows for this plugin
  74. */
  75. static char *allow_methods;
  76. /**
  77. * Ego list
  78. */
  79. static struct EgoEntry *ego_head;
  80. /**
  81. * Ego list
  82. */
  83. static struct EgoEntry *ego_tail;
  84. /**
  85. * The processing state
  86. */
  87. static int state;
  88. /**
  89. * Handle to Identity service.
  90. */
  91. static struct GNUNET_IDENTITY_Handle *identity_handle;
  92. /**
  93. * Identity Provider
  94. */
  95. static struct GNUNET_RECLAIM_Handle *idp;
  96. /**
  97. * @brief struct returned by the initialization function of the plugin
  98. */
  99. struct Plugin
  100. {
  101. const struct GNUNET_CONFIGURATION_Handle *cfg;
  102. };
  103. /**
  104. * The ego list
  105. */
  106. struct EgoEntry
  107. {
  108. /**
  109. * DLL
  110. */
  111. struct EgoEntry *next;
  112. /**
  113. * DLL
  114. */
  115. struct EgoEntry *prev;
  116. /**
  117. * Ego Identifier
  118. */
  119. char *identifier;
  120. /**
  121. * Public key string
  122. */
  123. char *keystring;
  124. /**
  125. * The Ego
  126. */
  127. struct GNUNET_IDENTITY_Ego *ego;
  128. };
  129. struct RequestHandle
  130. {
  131. /**
  132. * DLL
  133. */
  134. struct RequestHandle *next;
  135. /**
  136. * DLL
  137. */
  138. struct RequestHandle *prev;
  139. /**
  140. * Selected ego
  141. */
  142. struct EgoEntry *ego_entry;
  143. /**
  144. * Pointer to ego private key
  145. */
  146. struct GNUNET_IDENTITY_PrivateKey priv_key;
  147. /**
  148. * Rest connection
  149. */
  150. struct GNUNET_REST_RequestHandle *rest_handle;
  151. /**
  152. * Attribute claim list
  153. */
  154. struct GNUNET_RECLAIM_AttributeList *attr_list;
  155. /**
  156. * IDENTITY Operation
  157. */
  158. struct GNUNET_IDENTITY_Operation *op;
  159. /**
  160. * Idp Operation
  161. */
  162. struct GNUNET_RECLAIM_Operation *idp_op;
  163. /**
  164. * Attribute iterator
  165. */
  166. struct GNUNET_RECLAIM_AttributeIterator *attr_it;
  167. /**
  168. * Attribute iterator
  169. */
  170. struct GNUNET_RECLAIM_CredentialIterator *cred_it;
  171. /**
  172. * Ticket iterator
  173. */
  174. struct GNUNET_RECLAIM_TicketIterator *ticket_it;
  175. /**
  176. * A ticket
  177. */
  178. struct GNUNET_RECLAIM_Ticket ticket;
  179. /**
  180. * Desired timeout for the lookup (default is no timeout).
  181. */
  182. struct GNUNET_TIME_Relative timeout;
  183. /**
  184. * ID of a task associated with the resolution process.
  185. */
  186. struct GNUNET_SCHEDULER_Task *timeout_task;
  187. /**
  188. * The plugin result processor
  189. */
  190. GNUNET_REST_ResultProcessor proc;
  191. /**
  192. * The closure of the result processor
  193. */
  194. void *proc_cls;
  195. /**
  196. * The url
  197. */
  198. char *url;
  199. /**
  200. * Error response message
  201. */
  202. char *emsg;
  203. /**
  204. * Response code
  205. */
  206. int response_code;
  207. /**
  208. * Response object
  209. */
  210. json_t *resp_object;
  211. };
  212. /**
  213. * DLL
  214. */
  215. static struct RequestHandle *requests_head;
  216. /**
  217. * DLL
  218. */
  219. static struct RequestHandle *requests_tail;
  220. /**
  221. * Cleanup lookup handle
  222. * @param handle Handle to clean up
  223. */
  224. static void
  225. cleanup_handle (void *cls)
  226. {
  227. struct RequestHandle *handle = cls;
  228. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
  229. if (NULL != handle->resp_object)
  230. json_decref (handle->resp_object);
  231. if (NULL != handle->timeout_task)
  232. GNUNET_SCHEDULER_cancel (handle->timeout_task);
  233. if (NULL != handle->attr_it)
  234. GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
  235. if (NULL != handle->cred_it)
  236. GNUNET_RECLAIM_get_credentials_stop (handle->cred_it);
  237. if (NULL != handle->ticket_it)
  238. GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
  239. if (NULL != handle->url)
  240. GNUNET_free (handle->url);
  241. if (NULL != handle->emsg)
  242. GNUNET_free (handle->emsg);
  243. if (NULL != handle->attr_list)
  244. GNUNET_RECLAIM_attribute_list_destroy (handle->attr_list);
  245. GNUNET_CONTAINER_DLL_remove (requests_head,
  246. requests_tail,
  247. handle);
  248. GNUNET_free (handle);
  249. }
  250. /**
  251. * Task run on error, sends error message. Cleans up everything.
  252. *
  253. * @param cls the `struct RequestHandle`
  254. */
  255. static void
  256. do_error (void *cls)
  257. {
  258. struct RequestHandle *handle = cls;
  259. struct MHD_Response *resp;
  260. char *json_error;
  261. GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\" }", handle->emsg);
  262. if (0 == handle->response_code)
  263. {
  264. handle->response_code = MHD_HTTP_BAD_REQUEST;
  265. }
  266. resp = GNUNET_REST_create_response (json_error);
  267. MHD_add_response_header (resp, "Content-Type", "application/json");
  268. handle->proc (handle->proc_cls, resp, handle->response_code);
  269. cleanup_handle (handle);
  270. GNUNET_free (json_error);
  271. }
  272. /**
  273. * Task run on timeout, sends error message. Cleans up everything.
  274. *
  275. * @param cls the `struct RequestHandle`
  276. */
  277. static void
  278. do_timeout (void *cls)
  279. {
  280. struct RequestHandle *handle = cls;
  281. handle->timeout_task = NULL;
  282. do_error (handle);
  283. }
  284. static void
  285. collect_error_cb (void *cls)
  286. {
  287. GNUNET_SCHEDULER_add_now (&do_error, cls);
  288. }
  289. static void
  290. finished_cont (void *cls, int32_t success, const char *emsg)
  291. {
  292. struct RequestHandle *handle = cls;
  293. struct MHD_Response *resp;
  294. handle->idp_op = NULL;
  295. if (GNUNET_OK != success)
  296. {
  297. GNUNET_SCHEDULER_add_now (&do_error, handle);
  298. return;
  299. }
  300. resp = GNUNET_REST_create_response (emsg);
  301. GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
  302. "Content-Type",
  303. "application/json"));
  304. GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
  305. "Access-Control-Allow-Methods",
  306. allow_methods));
  307. handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
  308. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  309. }
  310. static void
  311. delete_finished_cb (void *cls, int32_t success, const char *emsg)
  312. {
  313. struct RequestHandle *handle = cls;
  314. struct MHD_Response *resp;
  315. if (GNUNET_OK != success)
  316. {
  317. GNUNET_SCHEDULER_add_now (&do_error, handle);
  318. return;
  319. }
  320. resp = GNUNET_REST_create_response (emsg);
  321. GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
  322. "Access-Control-Allow-Methods",
  323. allow_methods));
  324. handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
  325. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  326. }
  327. /**
  328. * Return attributes for identity
  329. *
  330. * @param cls the request handle
  331. */
  332. static void
  333. return_response (void *cls)
  334. {
  335. char *result_str;
  336. struct RequestHandle *handle = cls;
  337. struct MHD_Response *resp;
  338. result_str = json_dumps (handle->resp_object, 0);
  339. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
  340. resp = GNUNET_REST_create_response (result_str);
  341. GNUNET_assert (MHD_NO !=
  342. MHD_add_response_header (resp,
  343. "Access-Control-Allow-Methods",
  344. allow_methods));
  345. handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
  346. GNUNET_free (result_str);
  347. cleanup_handle (handle);
  348. }
  349. static void
  350. collect_finished_cb (void *cls)
  351. {
  352. struct RequestHandle *handle = cls;
  353. // Done
  354. handle->attr_it = NULL;
  355. handle->cred_it = NULL;
  356. handle->ticket_it = NULL;
  357. GNUNET_SCHEDULER_add_now (&return_response, handle);
  358. }
  359. /**
  360. * Collect all attributes for an ego
  361. *
  362. */
  363. static void
  364. ticket_collect (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
  365. {
  366. json_t *json_resource;
  367. struct RequestHandle *handle = cls;
  368. json_t *value;
  369. char *tmp;
  370. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
  371. tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(ticket->rnd));
  372. json_resource = json_object ();
  373. GNUNET_free (tmp);
  374. json_array_append (handle->resp_object, json_resource);
  375. tmp =
  376. GNUNET_STRINGS_data_to_string_alloc (&ticket->identity,
  377. sizeof(struct
  378. GNUNET_IDENTITY_PublicKey));
  379. value = json_string (tmp);
  380. json_object_set_new (json_resource, "issuer", value);
  381. GNUNET_free (tmp);
  382. tmp =
  383. GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
  384. sizeof(struct
  385. GNUNET_IDENTITY_PublicKey));
  386. value = json_string (tmp);
  387. json_object_set_new (json_resource, "audience", value);
  388. GNUNET_free (tmp);
  389. tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(ticket->rnd));
  390. value = json_string (tmp);
  391. json_object_set_new (json_resource, "rnd", value);
  392. GNUNET_free (tmp);
  393. GNUNET_RECLAIM_ticket_iteration_next (handle->ticket_it);
  394. }
  395. static void
  396. add_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
  397. const char *url,
  398. void *cls)
  399. {
  400. struct RequestHandle *handle = cls;
  401. const struct GNUNET_IDENTITY_PrivateKey *identity_priv;
  402. const char *identity;
  403. struct EgoEntry *ego_entry;
  404. struct GNUNET_RECLAIM_Credential *attribute;
  405. struct GNUNET_TIME_Relative exp;
  406. char term_data[handle->rest_handle->data_size + 1];
  407. json_t *data_json;
  408. json_error_t err;
  409. struct GNUNET_JSON_Specification attrspec[] =
  410. { GNUNET_RECLAIM_JSON_spec_credential (&attribute),
  411. GNUNET_JSON_spec_end () };
  412. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  413. "Adding an credential for %s.\n",
  414. handle->url);
  415. if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
  416. handle->url))
  417. {
  418. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
  419. GNUNET_SCHEDULER_add_now (&do_error, handle);
  420. return;
  421. }
  422. identity = handle->url + strlen (
  423. GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1;
  424. for (ego_entry = ego_head; NULL != ego_entry;
  425. ego_entry = ego_entry->next)
  426. if (0 == strcmp (identity, ego_entry->identifier))
  427. break;
  428. if (NULL == ego_entry)
  429. {
  430. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
  431. return;
  432. }
  433. identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
  434. if (0 >= handle->rest_handle->data_size)
  435. {
  436. GNUNET_SCHEDULER_add_now (&do_error, handle);
  437. return;
  438. }
  439. term_data[handle->rest_handle->data_size] = '\0';
  440. GNUNET_memcpy (term_data,
  441. handle->rest_handle->data,
  442. handle->rest_handle->data_size);
  443. data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
  444. if (GNUNET_OK != GNUNET_JSON_parse (data_json, attrspec, NULL, NULL))
  445. {
  446. json_decref (data_json);
  447. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  448. "Unable to parse JSON from %s\n",
  449. term_data);
  450. GNUNET_SCHEDULER_add_now (&do_error, handle);
  451. return;
  452. }
  453. json_decref (data_json);
  454. if (NULL == attribute)
  455. {
  456. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  457. "Unable to parse credential from %s\n",
  458. term_data);
  459. GNUNET_SCHEDULER_add_now (&do_error, handle);
  460. return;
  461. }
  462. /**
  463. * New ID for attribute
  464. */
  465. if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id))
  466. GNUNET_RECLAIM_id_generate (&attribute->id);
  467. exp = GNUNET_TIME_UNIT_HOURS;
  468. handle->idp_op = GNUNET_RECLAIM_credential_store (idp,
  469. identity_priv,
  470. attribute,
  471. &exp,
  472. &finished_cont,
  473. handle);
  474. GNUNET_JSON_parse_free (attrspec);
  475. }
  476. /**
  477. * Collect all credentials for an ego
  478. *
  479. */
  480. static void
  481. cred_collect (void *cls,
  482. const struct GNUNET_IDENTITY_PublicKey *identity,
  483. const struct GNUNET_RECLAIM_Credential *cred)
  484. {
  485. struct RequestHandle *handle = cls;
  486. struct GNUNET_RECLAIM_AttributeList *attrs;
  487. struct GNUNET_RECLAIM_AttributeListEntry *ale;
  488. struct GNUNET_TIME_Absolute exp;
  489. json_t *attr_obj;
  490. json_t *cred_obj;
  491. const char *type;
  492. char *tmp_value;
  493. char *id_str;
  494. char *issuer;
  495. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential: %s\n",
  496. cred->name);
  497. attrs = GNUNET_RECLAIM_credential_get_attributes (cred);
  498. issuer = GNUNET_RECLAIM_credential_get_issuer (cred);
  499. tmp_value = GNUNET_RECLAIM_credential_value_to_string (cred->type,
  500. cred->data,
  501. cred->data_size);
  502. cred_obj = json_object ();
  503. json_object_set_new (cred_obj, "value", json_string (tmp_value));
  504. json_object_set_new (cred_obj, "name", json_string (cred->name));
  505. type = GNUNET_RECLAIM_credential_number_to_typename (cred->type);
  506. json_object_set_new (cred_obj, "type", json_string (type));
  507. if (NULL != issuer)
  508. {
  509. json_object_set_new (cred_obj, "issuer", json_string (issuer));
  510. GNUNET_free (issuer);
  511. }
  512. if (GNUNET_OK == GNUNET_RECLAIM_credential_get_expiration (cred,
  513. &exp))
  514. {
  515. json_object_set_new (cred_obj, "expiration", json_integer (
  516. exp.abs_value_us));
  517. }
  518. id_str = GNUNET_STRINGS_data_to_string_alloc (&cred->id,
  519. sizeof(cred->id));
  520. json_object_set_new (cred_obj, "id", json_string (id_str));
  521. GNUNET_free (tmp_value);
  522. GNUNET_free (id_str);
  523. if (NULL != attrs)
  524. {
  525. json_t *attr_arr = json_array ();
  526. for (ale = attrs->list_head; NULL != ale; ale = ale->next)
  527. {
  528. tmp_value =
  529. GNUNET_RECLAIM_attribute_value_to_string (ale->attribute->type,
  530. ale->attribute->data,
  531. ale->attribute->data_size);
  532. attr_obj = json_object ();
  533. json_object_set_new (attr_obj, "value", json_string (tmp_value));
  534. json_object_set_new (attr_obj, "name", json_string (
  535. ale->attribute->name));
  536. json_object_set_new (attr_obj, "flag", json_string ("1")); // FIXME
  537. type = GNUNET_RECLAIM_attribute_number_to_typename (ale->attribute->type);
  538. json_object_set_new (attr_obj, "type", json_string (type));
  539. json_object_set_new (attr_obj, "id", json_string (""));
  540. json_object_set_new (attr_obj, "credential", json_string (""));
  541. json_array_append_new (attr_arr, attr_obj);
  542. GNUNET_free (tmp_value);
  543. }
  544. json_object_set_new (cred_obj, "attributes", attr_arr);
  545. }
  546. json_array_append_new (handle->resp_object, cred_obj);
  547. if (NULL != attrs)
  548. GNUNET_RECLAIM_attribute_list_destroy (attrs);
  549. GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
  550. }
  551. /**
  552. * Lists credential for identity request
  553. *
  554. * @param con_handle the connection handle
  555. * @param url the url
  556. * @param cls the RequestHandle
  557. */
  558. static void
  559. list_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
  560. const char *url,
  561. void *cls)
  562. {
  563. struct RequestHandle *handle = cls;
  564. const struct GNUNET_IDENTITY_PrivateKey *priv_key;
  565. struct EgoEntry *ego_entry;
  566. char *identity;
  567. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  568. "Getting credentials for %s.\n",
  569. handle->url);
  570. if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
  571. handle->url))
  572. {
  573. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
  574. GNUNET_SCHEDULER_add_now (&do_error, handle);
  575. return;
  576. }
  577. identity = handle->url + strlen (
  578. GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1;
  579. for (ego_entry = ego_head; NULL != ego_entry;
  580. ego_entry = ego_entry->next)
  581. if (0 == strcmp (identity, ego_entry->identifier))
  582. break;
  583. handle->resp_object = json_array ();
  584. if (NULL == ego_entry)
  585. {
  586. // Done
  587. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
  588. GNUNET_SCHEDULER_add_now (&return_response, handle);
  589. return;
  590. }
  591. priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
  592. handle->cred_it = GNUNET_RECLAIM_get_credentials_start (idp,
  593. priv_key,
  594. &collect_error_cb,
  595. handle,
  596. &cred_collect,
  597. handle,
  598. &
  599. collect_finished_cb,
  600. handle);
  601. }
  602. /**
  603. * Deletes credential from an identity
  604. *
  605. * @param con_handle the connection handle
  606. * @param url the url
  607. * @param cls the RequestHandle
  608. */
  609. static void
  610. delete_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
  611. const char *url,
  612. void *cls)
  613. {
  614. struct RequestHandle *handle = cls;
  615. const struct GNUNET_IDENTITY_PrivateKey *priv_key;
  616. struct GNUNET_RECLAIM_Credential attr;
  617. struct EgoEntry *ego_entry;
  618. char *identity_id_str;
  619. char *identity;
  620. char *id;
  621. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting credential.\n");
  622. if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
  623. handle->url))
  624. {
  625. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
  626. GNUNET_SCHEDULER_add_now (&do_error, handle);
  627. return;
  628. }
  629. identity_id_str =
  630. strdup (handle->url + strlen (
  631. GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1);
  632. identity = strtok (identity_id_str, "/");
  633. id = strtok (NULL, "/");
  634. if ((NULL == identity) || (NULL == id))
  635. {
  636. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
  637. GNUNET_free (identity_id_str);
  638. GNUNET_SCHEDULER_add_now (&do_error, handle);
  639. return;
  640. }
  641. for (ego_entry = ego_head; NULL != ego_entry;
  642. ego_entry = ego_entry->next)
  643. if (0 == strcmp (identity, ego_entry->identifier))
  644. break;
  645. handle->resp_object = json_array ();
  646. if (NULL == ego_entry)
  647. {
  648. // Done
  649. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
  650. GNUNET_free (identity_id_str);
  651. GNUNET_SCHEDULER_add_now (&return_response, handle);
  652. return;
  653. }
  654. priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
  655. memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Credential));
  656. GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
  657. attr.name = "";
  658. handle->idp_op = GNUNET_RECLAIM_credential_delete (idp,
  659. priv_key,
  660. &attr,
  661. &delete_finished_cb,
  662. handle);
  663. GNUNET_free (identity_id_str);
  664. }
  665. /**
  666. * List tickets for identity request
  667. *
  668. * @param con_handle the connection handle
  669. * @param url the url
  670. * @param cls the RequestHandle
  671. */
  672. static void
  673. list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
  674. const char *url,
  675. void *cls)
  676. {
  677. const struct GNUNET_IDENTITY_PrivateKey *priv_key;
  678. struct RequestHandle *handle = cls;
  679. struct EgoEntry *ego_entry;
  680. char *identity;
  681. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  682. "Getting tickets for %s.\n",
  683. handle->url);
  684. if (strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >= strlen (handle->url))
  685. {
  686. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
  687. GNUNET_SCHEDULER_add_now (&do_error, handle);
  688. return;
  689. }
  690. identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
  691. for (ego_entry = ego_head; NULL != ego_entry;
  692. ego_entry = ego_entry->next)
  693. if (0 == strcmp (identity, ego_entry->identifier))
  694. break;
  695. handle->resp_object = json_array ();
  696. if (NULL == ego_entry)
  697. {
  698. // Done
  699. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
  700. GNUNET_SCHEDULER_add_now (&return_response, handle);
  701. return;
  702. }
  703. priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
  704. handle->ticket_it =
  705. GNUNET_RECLAIM_ticket_iteration_start (idp,
  706. priv_key,
  707. &collect_error_cb,
  708. handle,
  709. &ticket_collect,
  710. handle,
  711. &collect_finished_cb,
  712. handle);
  713. }
  714. static void
  715. add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
  716. const char *url,
  717. void *cls)
  718. {
  719. const struct GNUNET_IDENTITY_PrivateKey *identity_priv;
  720. const char *identity;
  721. struct RequestHandle *handle = cls;
  722. struct EgoEntry *ego_entry;
  723. struct GNUNET_RECLAIM_Attribute *attribute;
  724. struct GNUNET_TIME_Relative exp;
  725. char term_data[handle->rest_handle->data_size + 1];
  726. json_t *data_json;
  727. json_error_t err;
  728. struct GNUNET_JSON_Specification attrspec[] =
  729. { GNUNET_RECLAIM_JSON_spec_attribute (&attribute), GNUNET_JSON_spec_end () };
  730. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  731. "Adding an attribute for %s.\n",
  732. handle->url);
  733. if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
  734. {
  735. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
  736. GNUNET_SCHEDULER_add_now (&do_error, handle);
  737. return;
  738. }
  739. identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
  740. for (ego_entry = ego_head; NULL != ego_entry;
  741. ego_entry = ego_entry->next)
  742. if (0 == strcmp (identity, ego_entry->identifier))
  743. break;
  744. if (NULL == ego_entry)
  745. {
  746. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
  747. return;
  748. }
  749. identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
  750. if (0 >= handle->rest_handle->data_size)
  751. {
  752. GNUNET_SCHEDULER_add_now (&do_error, handle);
  753. return;
  754. }
  755. term_data[handle->rest_handle->data_size] = '\0';
  756. GNUNET_memcpy (term_data,
  757. handle->rest_handle->data,
  758. handle->rest_handle->data_size);
  759. data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
  760. GNUNET_assert (GNUNET_OK ==
  761. GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
  762. json_decref (data_json);
  763. if (NULL == attribute)
  764. {
  765. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  766. "Unable to parse attribute from %s\n",
  767. term_data);
  768. GNUNET_SCHEDULER_add_now (&do_error, handle);
  769. return;
  770. }
  771. /**
  772. * New ID for attribute
  773. */
  774. if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id))
  775. GNUNET_RECLAIM_id_generate (&attribute->id);
  776. exp = GNUNET_TIME_UNIT_HOURS;
  777. handle->idp_op = GNUNET_RECLAIM_attribute_store (idp,
  778. identity_priv,
  779. attribute,
  780. &exp,
  781. &finished_cont,
  782. handle);
  783. GNUNET_JSON_parse_free (attrspec);
  784. }
  785. /**
  786. * Parse a JWT and return the respective claim value as Attribute
  787. *
  788. * @param cred the jwt credential
  789. * @param claim the name of the claim in the JWT
  790. *
  791. * @return a GNUNET_RECLAIM_Attribute, containing the new value
  792. */
  793. struct GNUNET_RECLAIM_Attribute *
  794. parse_jwt (const struct GNUNET_RECLAIM_Credential *cred,
  795. const char *claim)
  796. {
  797. char *jwt_string;
  798. struct GNUNET_RECLAIM_Attribute *attr;
  799. char delim[] = ".";
  800. const char *type_str = NULL;
  801. const char *val_str = NULL;
  802. char *data;
  803. size_t data_size;
  804. uint32_t type;
  805. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
  806. char *decoded_jwt;
  807. json_t *json_val;
  808. json_error_t *json_err = NULL;
  809. jwt_string = GNUNET_RECLAIM_credential_value_to_string (cred->type,
  810. cred->data,
  811. cred->data_size);
  812. char *jwt_body = strtok (jwt_string, delim);
  813. jwt_body = strtok (NULL, delim);
  814. GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
  815. (void **) &decoded_jwt);
  816. json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
  817. const char *key;
  818. json_t *value;
  819. json_object_foreach (json_val, key, value) {
  820. if (0 == strcasecmp (key,claim))
  821. {
  822. val_str = json_dumps (value, JSON_ENCODE_ANY);
  823. }
  824. }
  825. type_str = "String";
  826. type = GNUNET_RECLAIM_attribute_typename_to_number (type_str);
  827. if (GNUNET_SYSERR == GNUNET_RECLAIM_attribute_string_to_value (type,val_str,
  828. (void **) &data,
  829. &data_size))
  830. {
  831. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  832. "Attribute value from JWT Parser invalid!\n");
  833. GNUNET_RECLAIM_attribute_string_to_value (type,
  834. "Error: Referenced Claim Name not Found",
  835. (void **) &data,
  836. &data_size);
  837. attr = GNUNET_RECLAIM_attribute_new (claim, &cred->id,
  838. type, data, data_size);
  839. attr->id = cred->id;
  840. attr->flag = 1;
  841. }
  842. else
  843. {
  844. attr = GNUNET_RECLAIM_attribute_new (claim, &cred->id,
  845. type, data, data_size);
  846. attr->id = cred->id;
  847. attr->flag = 1;
  848. }
  849. return attr;
  850. }
  851. /**
  852. * Collect all attributes for an ego
  853. *
  854. */
  855. static void
  856. attr_collect (void *cls,
  857. const struct GNUNET_IDENTITY_PublicKey *identity,
  858. const struct GNUNET_RECLAIM_Attribute *attr)
  859. {
  860. struct RequestHandle *handle = cls;
  861. json_t *attr_obj;
  862. const char *type;
  863. char *id_str;
  864. char *tmp_value;
  865. tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
  866. attr->data,
  867. attr->data_size);
  868. attr_obj = json_object ();
  869. json_object_set_new (attr_obj, "value", json_string (tmp_value));
  870. json_object_set_new (attr_obj, "name", json_string (attr->name));
  871. if (GNUNET_RECLAIM_id_is_zero (&attr->credential))
  872. json_object_set_new (attr_obj, "flag", json_string ("0"));
  873. else
  874. json_object_set_new (attr_obj, "flag", json_string ("1"));
  875. type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
  876. json_object_set_new (attr_obj, "type", json_string (type));
  877. id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id,
  878. sizeof(attr->id));
  879. json_object_set_new (attr_obj, "id", json_string (id_str));
  880. GNUNET_free (id_str);
  881. id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->credential,
  882. sizeof(attr->credential));
  883. json_object_set_new (attr_obj, "credential", json_string (id_str));
  884. GNUNET_free (id_str);
  885. json_array_append (handle->resp_object, attr_obj);
  886. json_decref (attr_obj);
  887. GNUNET_free (tmp_value);
  888. GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
  889. }
  890. /**
  891. * List attributes for identity request
  892. *
  893. * @param con_handle the connection handle
  894. * @param url the url
  895. * @param cls the RequestHandle
  896. */
  897. static void
  898. list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
  899. const char *url,
  900. void *cls)
  901. {
  902. const struct GNUNET_IDENTITY_PrivateKey *priv_key;
  903. struct RequestHandle *handle = cls;
  904. struct EgoEntry *ego_entry;
  905. char *identity;
  906. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  907. "Getting attributes for %s.\n",
  908. handle->url);
  909. if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
  910. {
  911. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
  912. GNUNET_SCHEDULER_add_now (&do_error, handle);
  913. return;
  914. }
  915. identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
  916. for (ego_entry = ego_head; NULL != ego_entry;
  917. ego_entry = ego_entry->next)
  918. if (0 == strcmp (identity, ego_entry->identifier))
  919. break;
  920. handle->resp_object = json_array ();
  921. if (NULL == ego_entry)
  922. {
  923. // Done
  924. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
  925. GNUNET_SCHEDULER_add_now (&return_response, handle);
  926. return;
  927. }
  928. priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
  929. handle->attr_it = GNUNET_RECLAIM_get_attributes_start (idp,
  930. priv_key,
  931. &collect_error_cb,
  932. handle,
  933. &attr_collect,
  934. handle,
  935. &collect_finished_cb,
  936. handle);
  937. }
  938. /**
  939. * List attributes for identity request
  940. *
  941. * @param con_handle the connection handle
  942. * @param url the url
  943. * @param cls the RequestHandle
  944. */
  945. static void
  946. delete_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
  947. const char *url,
  948. void *cls)
  949. {
  950. const struct GNUNET_IDENTITY_PrivateKey *priv_key;
  951. struct RequestHandle *handle = cls;
  952. struct GNUNET_RECLAIM_Attribute attr;
  953. struct EgoEntry *ego_entry;
  954. char *identity_id_str;
  955. char *identity;
  956. char *id;
  957. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting attributes.\n");
  958. if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
  959. {
  960. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
  961. GNUNET_SCHEDULER_add_now (&do_error, handle);
  962. return;
  963. }
  964. identity_id_str =
  965. strdup (handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1);
  966. identity = strtok (identity_id_str, "/");
  967. id = strtok (NULL, "/");
  968. if ((NULL == identity) || (NULL == id))
  969. {
  970. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
  971. GNUNET_free (identity_id_str);
  972. GNUNET_SCHEDULER_add_now (&do_error, handle);
  973. return;
  974. }
  975. for (ego_entry = ego_head; NULL != ego_entry;
  976. ego_entry = ego_entry->next)
  977. if (0 == strcmp (identity, ego_entry->identifier))
  978. break;
  979. handle->resp_object = json_array ();
  980. if (NULL == ego_entry)
  981. {
  982. // Done
  983. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
  984. GNUNET_free (identity_id_str);
  985. GNUNET_SCHEDULER_add_now (&return_response, handle);
  986. return;
  987. }
  988. priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
  989. memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Attribute));
  990. GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
  991. attr.name = "";
  992. handle->idp_op = GNUNET_RECLAIM_attribute_delete (idp,
  993. priv_key,
  994. &attr,
  995. &delete_finished_cb,
  996. handle);
  997. GNUNET_free (identity_id_str);
  998. }
  999. static void
  1000. revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
  1001. const char *url,
  1002. void *cls)
  1003. {
  1004. const struct GNUNET_IDENTITY_PrivateKey *identity_priv;
  1005. struct RequestHandle *handle = cls;
  1006. struct EgoEntry *ego_entry;
  1007. struct GNUNET_RECLAIM_Ticket *ticket = NULL;
  1008. struct GNUNET_IDENTITY_PublicKey tmp_pk;
  1009. char term_data[handle->rest_handle->data_size + 1];
  1010. json_t *data_json;
  1011. json_error_t err;
  1012. struct GNUNET_JSON_Specification tktspec[] =
  1013. { GNUNET_RECLAIM_JSON_spec_ticket (&ticket), GNUNET_JSON_spec_end () };
  1014. if (0 >= handle->rest_handle->data_size)
  1015. {
  1016. GNUNET_SCHEDULER_add_now (&do_error, handle);
  1017. return;
  1018. }
  1019. term_data[handle->rest_handle->data_size] = '\0';
  1020. GNUNET_memcpy (term_data,
  1021. handle->rest_handle->data,
  1022. handle->rest_handle->data_size);
  1023. data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
  1024. if ((NULL == data_json) ||
  1025. (GNUNET_OK != GNUNET_JSON_parse (data_json, tktspec, NULL, NULL)))
  1026. {
  1027. handle->emsg = GNUNET_strdup ("Not a ticket!\n");
  1028. GNUNET_SCHEDULER_add_now (&do_error, handle);
  1029. GNUNET_JSON_parse_free (tktspec);
  1030. if (NULL != data_json)
  1031. json_decref (data_json);
  1032. return;
  1033. }
  1034. json_decref (data_json);
  1035. if (NULL == ticket)
  1036. {
  1037. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1038. "Unable to parse ticket from %s\n",
  1039. term_data);
  1040. GNUNET_SCHEDULER_add_now (&do_error, handle);
  1041. return;
  1042. }
  1043. for (ego_entry = ego_head; NULL != ego_entry;
  1044. ego_entry = ego_entry->next)
  1045. {
  1046. GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &tmp_pk);
  1047. if (0 == memcmp (&ticket->identity,
  1048. &tmp_pk,
  1049. sizeof(struct GNUNET_IDENTITY_PublicKey)))
  1050. break;
  1051. }
  1052. if (NULL == ego_entry)
  1053. {
  1054. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown\n");
  1055. GNUNET_JSON_parse_free (tktspec);
  1056. return;
  1057. }
  1058. identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
  1059. handle->idp_op = GNUNET_RECLAIM_ticket_revoke (idp,
  1060. identity_priv,
  1061. ticket,
  1062. &finished_cont,
  1063. handle);
  1064. GNUNET_JSON_parse_free (tktspec);
  1065. }
  1066. static void
  1067. consume_cont (void *cls,
  1068. const struct GNUNET_IDENTITY_PublicKey *identity,
  1069. const struct GNUNET_RECLAIM_Attribute *attr,
  1070. const struct GNUNET_RECLAIM_Presentation *presentation)
  1071. {
  1072. struct RequestHandle *handle = cls;
  1073. char *val_str;
  1074. json_t *value;
  1075. if (NULL == identity)
  1076. {
  1077. GNUNET_SCHEDULER_add_now (&return_response, handle);
  1078. return;
  1079. }
  1080. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name);
  1081. val_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
  1082. attr->data,
  1083. attr->data_size);
  1084. if (NULL == val_str)
  1085. {
  1086. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1087. "Failed to parse value for: %s\n",
  1088. attr->name);
  1089. return;
  1090. }
  1091. value = json_string (val_str);
  1092. json_object_set_new (handle->resp_object, attr->name, value);
  1093. json_decref (value);
  1094. GNUNET_free (val_str);
  1095. }
  1096. static void
  1097. consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
  1098. const char *url,
  1099. void *cls)
  1100. {
  1101. const struct GNUNET_IDENTITY_PrivateKey *identity_priv;
  1102. struct RequestHandle *handle = cls;
  1103. struct EgoEntry *ego_entry;
  1104. struct GNUNET_RECLAIM_Ticket *ticket;
  1105. struct GNUNET_IDENTITY_PublicKey tmp_pk;
  1106. char term_data[handle->rest_handle->data_size + 1];
  1107. json_t *data_json;
  1108. json_error_t err;
  1109. struct GNUNET_JSON_Specification tktspec[] =
  1110. { GNUNET_RECLAIM_JSON_spec_ticket (&ticket), GNUNET_JSON_spec_end () };
  1111. if (0 >= handle->rest_handle->data_size)
  1112. {
  1113. GNUNET_SCHEDULER_add_now (&do_error, handle);
  1114. return;
  1115. }
  1116. term_data[handle->rest_handle->data_size] = '\0';
  1117. GNUNET_memcpy (term_data,
  1118. handle->rest_handle->data,
  1119. handle->rest_handle->data_size);
  1120. data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
  1121. if (NULL == data_json)
  1122. {
  1123. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1124. "Unable to parse JSON Object from %s\n",
  1125. term_data);
  1126. GNUNET_SCHEDULER_add_now (&do_error, handle);
  1127. return;
  1128. }
  1129. if (GNUNET_OK != GNUNET_JSON_parse (data_json, tktspec, NULL, NULL))
  1130. {
  1131. handle->emsg = GNUNET_strdup ("Not a ticket!\n");
  1132. GNUNET_SCHEDULER_add_now (&do_error, handle);
  1133. GNUNET_JSON_parse_free (tktspec);
  1134. json_decref (data_json);
  1135. return;
  1136. }
  1137. for (ego_entry = ego_head; NULL != ego_entry;
  1138. ego_entry = ego_entry->next)
  1139. {
  1140. GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &tmp_pk);
  1141. if (0 == memcmp (&ticket->audience,
  1142. &tmp_pk,
  1143. sizeof(struct GNUNET_IDENTITY_PublicKey)))
  1144. break;
  1145. }
  1146. if (NULL == ego_entry)
  1147. {
  1148. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown\n");
  1149. GNUNET_JSON_parse_free (tktspec);
  1150. return;
  1151. }
  1152. identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
  1153. handle->resp_object = json_object ();
  1154. handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
  1155. identity_priv,
  1156. ticket,
  1157. &consume_cont,
  1158. handle);
  1159. GNUNET_JSON_parse_free (tktspec);
  1160. }
  1161. /**
  1162. * Respond to OPTIONS request
  1163. *
  1164. * @param con_handle the connection handle
  1165. * @param url the url
  1166. * @param cls the RequestHandle
  1167. */
  1168. static void
  1169. options_cont (struct GNUNET_REST_RequestHandle *con_handle,
  1170. const char *url,
  1171. void *cls)
  1172. {
  1173. struct MHD_Response *resp;
  1174. struct RequestHandle *handle = cls;
  1175. // For now, independent of path return all options
  1176. resp = GNUNET_REST_create_response (NULL);
  1177. MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
  1178. handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
  1179. cleanup_handle (handle);
  1180. return;
  1181. }
  1182. /**
  1183. * If listing is enabled, prints information about the egos.
  1184. *
  1185. * This function is initially called for all egos and then again
  1186. * whenever a ego's identifier changes or if it is deleted. At the
  1187. * end of the initial pass over all egos, the function is once called
  1188. * with 'NULL' for 'ego'. That does NOT mean that the callback won't
  1189. * be invoked in the future or that there was an error.
  1190. *
  1191. * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', this
  1192. * function is only called ONCE, and 'NULL' being passed in 'ego' does
  1193. * indicate an error (for example because name is taken or no default value is
  1194. * known). If 'ego' is non-NULL and if '*ctx' is set in those callbacks, the
  1195. * value WILL be passed to a subsequent call to the identity callback of
  1196. * 'GNUNET_IDENTITY_connect' (if that one was not NULL).
  1197. *
  1198. * When an identity is renamed, this function is called with the
  1199. * (known) ego but the NEW identifier.
  1200. *
  1201. * When an identity is deleted, this function is called with the
  1202. * (known) ego and "NULL" for the 'identifier'. In this case,
  1203. * the 'ego' is henceforth invalid (and the 'ctx' should also be
  1204. * cleaned up).
  1205. *
  1206. * @param cls closure
  1207. * @param ego ego handle
  1208. * @param ctx context for application to store data for this ego
  1209. * (during the lifetime of this process, initially NULL)
  1210. * @param identifier identifier assigned by the user for this ego,
  1211. * NULL if the user just deleted the ego and it
  1212. * must thus no longer be used
  1213. */
  1214. static void
  1215. list_ego (void *cls,
  1216. struct GNUNET_IDENTITY_Ego *ego,
  1217. void **ctx,
  1218. const char *identifier)
  1219. {
  1220. struct EgoEntry *ego_entry;
  1221. struct GNUNET_IDENTITY_PublicKey pk;
  1222. if ((NULL == ego) && (ID_REST_STATE_INIT == state))
  1223. {
  1224. state = ID_REST_STATE_POST_INIT;
  1225. return;
  1226. }
  1227. if (ID_REST_STATE_INIT == state)
  1228. {
  1229. ego_entry = GNUNET_new (struct EgoEntry);
  1230. GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
  1231. ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk);
  1232. ego_entry->ego = ego;
  1233. ego_entry->identifier = GNUNET_strdup (identifier);
  1234. GNUNET_CONTAINER_DLL_insert_tail (ego_head,
  1235. ego_tail,
  1236. ego_entry);
  1237. }
  1238. /* Ego renamed or added */
  1239. if (identifier != NULL)
  1240. {
  1241. for (ego_entry = ego_head; NULL != ego_entry;
  1242. ego_entry = ego_entry->next)
  1243. {
  1244. if (ego_entry->ego == ego)
  1245. {
  1246. /* Rename */
  1247. GNUNET_free (ego_entry->identifier);
  1248. ego_entry->identifier = GNUNET_strdup (identifier);
  1249. break;
  1250. }
  1251. }
  1252. if (NULL == ego_entry)
  1253. {
  1254. /* Add */
  1255. ego_entry = GNUNET_new (struct EgoEntry);
  1256. GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
  1257. ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk);
  1258. ego_entry->ego = ego;
  1259. ego_entry->identifier = GNUNET_strdup (identifier);
  1260. GNUNET_CONTAINER_DLL_insert_tail (ego_head,
  1261. ego_tail,
  1262. ego_entry);
  1263. }
  1264. }
  1265. else
  1266. {
  1267. /* Delete */
  1268. for (ego_entry = ego_head; NULL != ego_entry;
  1269. ego_entry = ego_entry->next)
  1270. {
  1271. if (ego_entry->ego == ego)
  1272. break;
  1273. }
  1274. if (NULL == ego_entry)
  1275. return; /* Not found */
  1276. GNUNET_CONTAINER_DLL_remove (ego_head,
  1277. ego_tail,
  1278. ego_entry);
  1279. GNUNET_free (ego_entry->identifier);
  1280. GNUNET_free (ego_entry->keystring);
  1281. GNUNET_free (ego_entry);
  1282. return;
  1283. }
  1284. }
  1285. static enum GNUNET_GenericReturnValue
  1286. rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
  1287. GNUNET_REST_ResultProcessor proc,
  1288. void *proc_cls)
  1289. {
  1290. struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
  1291. struct GNUNET_REST_RequestHandlerError err;
  1292. static const struct GNUNET_REST_RequestHandler handlers[] =
  1293. { { MHD_HTTP_METHOD_GET,
  1294. GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &list_attribute_cont },
  1295. { MHD_HTTP_METHOD_POST,
  1296. GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &add_attribute_cont },
  1297. { MHD_HTTP_METHOD_DELETE,
  1298. GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &delete_attribute_cont },
  1299. { MHD_HTTP_METHOD_GET,
  1300. GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &list_credential_cont },
  1301. { MHD_HTTP_METHOD_POST,
  1302. GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &add_credential_cont },
  1303. { MHD_HTTP_METHOD_DELETE,
  1304. GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &delete_credential_cont },
  1305. { MHD_HTTP_METHOD_GET,
  1306. GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont },
  1307. { MHD_HTTP_METHOD_POST,
  1308. GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont },
  1309. { MHD_HTTP_METHOD_POST,
  1310. GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont },
  1311. { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_RECLAIM, &options_cont },
  1312. GNUNET_REST_HANDLER_END};
  1313. handle->response_code = 0;
  1314. handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
  1315. handle->proc_cls = proc_cls;
  1316. handle->proc = proc;
  1317. handle->rest_handle = rest_handle;
  1318. handle->url = GNUNET_strdup (rest_handle->url);
  1319. if (handle->url[strlen (handle->url) - 1] == '/')
  1320. handle->url[strlen (handle->url) - 1] = '\0';
  1321. handle->timeout_task =
  1322. GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
  1323. GNUNET_CONTAINER_DLL_insert (requests_head,
  1324. requests_tail,
  1325. handle);
  1326. if (GNUNET_NO ==
  1327. GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
  1328. {
  1329. cleanup_handle (handle);
  1330. return GNUNET_NO;
  1331. }
  1332. return GNUNET_YES;
  1333. }
  1334. /**
  1335. * Entry point for the plugin.
  1336. *
  1337. * @param cls Config info
  1338. * @return NULL on error, otherwise the plugin context
  1339. */
  1340. void *
  1341. libgnunet_plugin_rest_reclaim_init (void *cls)
  1342. {
  1343. static struct Plugin plugin;
  1344. struct GNUNET_REST_Plugin *api;
  1345. cfg = cls;
  1346. if (NULL != plugin.cfg)
  1347. return NULL; /* can only initialize once! */
  1348. memset (&plugin, 0, sizeof(struct Plugin));
  1349. plugin.cfg = cfg;
  1350. api = GNUNET_new (struct GNUNET_REST_Plugin);
  1351. api->cls = &plugin;
  1352. api->name = GNUNET_REST_API_NS_RECLAIM;
  1353. api->process_request = &rest_identity_process_request;
  1354. GNUNET_asprintf (&allow_methods,
  1355. "%s, %s, %s, %s, %s",
  1356. MHD_HTTP_METHOD_GET,
  1357. MHD_HTTP_METHOD_POST,
  1358. MHD_HTTP_METHOD_PUT,
  1359. MHD_HTTP_METHOD_DELETE,
  1360. MHD_HTTP_METHOD_OPTIONS);
  1361. identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
  1362. state = ID_REST_STATE_INIT;
  1363. idp = GNUNET_RECLAIM_connect (cfg);
  1364. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1365. _ ("Identity Provider REST API initialized\n"));
  1366. return api;
  1367. }
  1368. /**
  1369. * Exit point from the plugin.
  1370. *
  1371. * @param cls the plugin context (as returned by "init")
  1372. * @return always NULL
  1373. */
  1374. void *
  1375. libgnunet_plugin_rest_reclaim_done (void *cls)
  1376. {
  1377. struct GNUNET_REST_Plugin *api = cls;
  1378. struct Plugin *plugin = api->cls;
  1379. struct RequestHandle *request;
  1380. struct EgoEntry *ego_entry;
  1381. struct EgoEntry *ego_tmp;
  1382. plugin->cfg = NULL;
  1383. while (NULL != (request = requests_head))
  1384. do_error (request);
  1385. if (NULL != idp)
  1386. GNUNET_RECLAIM_disconnect (idp);
  1387. if (NULL != identity_handle)
  1388. GNUNET_IDENTITY_disconnect (identity_handle);
  1389. for (ego_entry = ego_head; NULL != ego_entry;)
  1390. {
  1391. ego_tmp = ego_entry;
  1392. ego_entry = ego_entry->next;
  1393. GNUNET_free (ego_tmp->identifier);
  1394. GNUNET_free (ego_tmp->keystring);
  1395. GNUNET_free (ego_tmp);
  1396. }
  1397. GNUNET_free (allow_methods);
  1398. GNUNET_free (api);
  1399. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1400. "Identity Provider REST plugin is finished\n");
  1401. return NULL;
  1402. }
  1403. /* end of plugin_rest_reclaim.c */