plugin_rest_identity.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433
  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 identity/plugin_rest_identity.c
  20. * @brief GNUnet Identity REST plugin
  21. */
  22. #include "platform.h"
  23. #include "gnunet_rest_plugin.h"
  24. #include "gnunet_identity_service.h"
  25. #include "gnunet_rest_lib.h"
  26. #include "microhttpd.h"
  27. #include <jansson.h>
  28. /**
  29. * Identity Namespace
  30. */
  31. #define GNUNET_REST_API_NS_IDENTITY "/identity"
  32. /**
  33. * Identity Namespace with public key specifier
  34. */
  35. #define GNUNET_REST_API_NS_IDENTITY_PUBKEY "/identity/pubkey"
  36. /**
  37. * Identity Namespace with public key specifier
  38. */
  39. #define GNUNET_REST_API_NS_IDENTITY_NAME "/identity/name"
  40. /**
  41. * Identity Subsystem Namespace
  42. */
  43. #define GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM "/identity/subsystem"
  44. /**
  45. * Parameter public key
  46. */
  47. #define GNUNET_REST_IDENTITY_PARAM_PUBKEY "pubkey"
  48. /**
  49. * Parameter private key
  50. */
  51. #define GNUNET_REST_IDENTITY_PARAM_PRIVKEY "privkey"
  52. /**
  53. * Parameter subsystem
  54. */
  55. #define GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM "subsystem"
  56. /**
  57. * Parameter name
  58. */
  59. #define GNUNET_REST_IDENTITY_PARAM_NAME "name"
  60. /**
  61. * Parameter new name
  62. */
  63. #define GNUNET_REST_IDENTITY_PARAM_NEWNAME "newname"
  64. /**
  65. * Error message Unknown Error
  66. */
  67. #define GNUNET_REST_IDENTITY_ERROR_UNKNOWN "Unknown Error"
  68. /**
  69. * Error message No identity found
  70. */
  71. #define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found"
  72. /**
  73. * Error message Missing identity name
  74. */
  75. #define GNUNET_REST_IDENTITY_MISSING_NAME "Missing identity name"
  76. /**
  77. * Error message Missing identity name
  78. */
  79. #define GNUNET_REST_IDENTITY_MISSING_PUBKEY "Missing identity public key"
  80. /**
  81. * Error message No data
  82. */
  83. #define GNUNET_REST_ERROR_NO_DATA "No data"
  84. /**
  85. * Error message Data invalid
  86. */
  87. #define GNUNET_REST_ERROR_DATA_INVALID "Data invalid"
  88. /**
  89. * State while collecting all egos
  90. */
  91. #define ID_REST_STATE_INIT 0
  92. /**
  93. * Done collecting egos
  94. */
  95. #define ID_REST_STATE_POST_INIT 1
  96. /**
  97. * The configuration handle
  98. */
  99. const struct GNUNET_CONFIGURATION_Handle *cfg;
  100. /**
  101. * HTTP methods allows for this plugin
  102. */
  103. static char *allow_methods;
  104. /**
  105. * @brief struct returned by the initialization function of the plugin
  106. */
  107. struct Plugin
  108. {
  109. const struct GNUNET_CONFIGURATION_Handle *cfg;
  110. };
  111. /**
  112. * The ego list
  113. */
  114. struct EgoEntry
  115. {
  116. /**
  117. * DLL
  118. */
  119. struct EgoEntry *next;
  120. /**
  121. * DLL
  122. */
  123. struct EgoEntry *prev;
  124. /**
  125. * Ego Identifier
  126. */
  127. char *identifier;
  128. /**
  129. * Public key string
  130. */
  131. char *keystring;
  132. /**
  133. * The Ego
  134. */
  135. struct GNUNET_IDENTITY_Ego *ego;
  136. };
  137. /**
  138. * The request handle
  139. */
  140. struct RequestHandle
  141. {
  142. /**
  143. * The data from the REST request
  144. */
  145. const char *data;
  146. /**
  147. * The name to look up
  148. */
  149. char *name;
  150. /**
  151. * the length of the REST data
  152. */
  153. size_t data_size;
  154. /**
  155. * Ego list
  156. */
  157. struct EgoEntry *ego_head;
  158. /**
  159. * Ego list
  160. */
  161. struct EgoEntry *ego_tail;
  162. /**
  163. * The processing state
  164. */
  165. int state;
  166. /**
  167. * Handle to Identity service.
  168. */
  169. struct GNUNET_IDENTITY_Handle *identity_handle;
  170. /**
  171. * IDENTITY Operation
  172. */
  173. struct GNUNET_IDENTITY_Operation *op;
  174. /**
  175. * Rest connection
  176. */
  177. struct GNUNET_REST_RequestHandle *rest_handle;
  178. /**
  179. * Desired timeout for the lookup (default is no timeout).
  180. */
  181. struct GNUNET_TIME_Relative timeout;
  182. /**
  183. * ID of a task associated with the resolution process.
  184. */
  185. struct GNUNET_SCHEDULER_Task *timeout_task;
  186. /**
  187. * The plugin result processor
  188. */
  189. GNUNET_REST_ResultProcessor proc;
  190. /**
  191. * The closure of the result processor
  192. */
  193. void *proc_cls;
  194. /**
  195. * The url
  196. */
  197. char *url;
  198. /**
  199. * Error response message
  200. */
  201. char *emsg;
  202. /**
  203. * Response code
  204. */
  205. int response_code;
  206. };
  207. /**
  208. * Cleanup lookup handle
  209. * @param handle Handle to clean up
  210. */
  211. static void
  212. cleanup_handle (void *cls)
  213. {
  214. struct RequestHandle *handle = cls;
  215. struct EgoEntry *ego_entry;
  216. struct EgoEntry *ego_tmp;
  217. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
  218. if (NULL != handle->timeout_task)
  219. {
  220. GNUNET_SCHEDULER_cancel (handle->timeout_task);
  221. handle->timeout_task = NULL;
  222. }
  223. if (NULL != handle->url)
  224. GNUNET_free (handle->url);
  225. if (NULL != handle->emsg)
  226. GNUNET_free (handle->emsg);
  227. if (NULL != handle->name)
  228. GNUNET_free (handle->name);
  229. if (NULL != handle->identity_handle)
  230. GNUNET_IDENTITY_disconnect (handle->identity_handle);
  231. for (ego_entry = handle->ego_head; NULL != ego_entry;)
  232. {
  233. ego_tmp = ego_entry;
  234. ego_entry = ego_entry->next;
  235. GNUNET_free (ego_tmp->identifier);
  236. GNUNET_free (ego_tmp->keystring);
  237. GNUNET_free (ego_tmp);
  238. }
  239. GNUNET_free (handle);
  240. }
  241. /**
  242. * Task run on errors. Reports an error and cleans up everything.
  243. *
  244. * @param cls the `struct RequestHandle`
  245. */
  246. static void
  247. do_error (void *cls)
  248. {
  249. struct RequestHandle *handle = cls;
  250. struct MHD_Response *resp;
  251. json_t *json_error = json_object ();
  252. char *response;
  253. if (NULL == handle->emsg)
  254. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_ERROR_UNKNOWN);
  255. json_object_set_new (json_error, "error", json_string (handle->emsg));
  256. if (0 == handle->response_code)
  257. handle->response_code = MHD_HTTP_OK;
  258. response = json_dumps (json_error, 0);
  259. resp = GNUNET_REST_create_response (response);
  260. MHD_add_response_header (resp, "Content-Type", "application/json");
  261. handle->proc (handle->proc_cls, resp, handle->response_code);
  262. json_decref (json_error);
  263. GNUNET_free (response);
  264. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  265. }
  266. /**
  267. * Get EgoEntry from list with either a public key or a name
  268. * If public key and name are not NULL, it returns the public key result first
  269. *
  270. * @param handle the RequestHandle
  271. * @param pubkey the public key of an identity (only one can be NULL)
  272. * @param name the name of an identity (only one can be NULL)
  273. * @return EgoEntry or NULL if not found
  274. */
  275. struct EgoEntry *
  276. get_egoentry (struct RequestHandle *handle, char *pubkey, char *name)
  277. {
  278. struct EgoEntry *ego_entry;
  279. if (NULL != pubkey)
  280. {
  281. for (ego_entry = handle->ego_head; NULL != ego_entry;
  282. ego_entry = ego_entry->next)
  283. {
  284. if (0 != strcasecmp (pubkey, ego_entry->keystring))
  285. continue;
  286. return ego_entry;
  287. }
  288. }
  289. if (NULL != name)
  290. {
  291. for (ego_entry = handle->ego_head; NULL != ego_entry;
  292. ego_entry = ego_entry->next)
  293. {
  294. if (0 != strcasecmp (name, ego_entry->identifier))
  295. continue;
  296. return ego_entry;
  297. }
  298. }
  299. return NULL;
  300. }
  301. /**
  302. * Callback for GET Request with subsystem
  303. *
  304. * @param cls the RequestHandle
  305. * @param ego the Ego found
  306. * @param ctx the context
  307. * @param name the id of the ego
  308. */
  309. static void
  310. ego_get_for_subsystem (void *cls,
  311. struct GNUNET_IDENTITY_Ego *ego,
  312. void **ctx,
  313. const char *name)
  314. {
  315. struct RequestHandle *handle = cls;
  316. struct MHD_Response *resp;
  317. struct GNUNET_CRYPTO_EcdsaPublicKey public_key;
  318. json_t *json_root;
  319. char *result_str;
  320. char *public_key_string;
  321. if (NULL == ego)
  322. {
  323. handle->response_code = MHD_HTTP_NOT_FOUND;
  324. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
  325. GNUNET_SCHEDULER_add_now (&do_error, handle);
  326. return;
  327. }
  328. GNUNET_IDENTITY_ego_get_public_key (ego, &public_key);
  329. public_key_string = GNUNET_CRYPTO_ecdsa_public_key_to_string (&public_key);
  330. // create json with subsystem identity
  331. json_root = json_object ();
  332. json_object_set_new (json_root,
  333. GNUNET_REST_IDENTITY_PARAM_PUBKEY,
  334. json_string (public_key_string));
  335. json_object_set_new (json_root,
  336. GNUNET_REST_IDENTITY_PARAM_NAME,
  337. json_string (name));
  338. result_str = json_dumps (json_root, 0);
  339. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
  340. resp = GNUNET_REST_create_response (result_str);
  341. MHD_add_response_header (resp, "Content-Type", "application/json");
  342. json_decref (json_root);
  343. handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
  344. GNUNET_free (result_str);
  345. GNUNET_free (public_key_string);
  346. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  347. }
  348. /**
  349. * Handle identity GET request for subsystem
  350. *
  351. * @param con_handle the connection handle
  352. * @param url the url
  353. * @param cls the RequestHandle
  354. */
  355. void
  356. ego_get_subsystem (struct GNUNET_REST_RequestHandle *con_handle,
  357. const char *url,
  358. void *cls)
  359. {
  360. struct RequestHandle *handle = cls;
  361. char *subsystem;
  362. if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
  363. {
  364. handle->emsg = GNUNET_strdup ("Missing subsystem name");
  365. GNUNET_SCHEDULER_add_now (&do_error, handle);
  366. return;
  367. }
  368. subsystem = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
  369. // requested default identity of subsystem
  370. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsystem);
  371. handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
  372. subsystem,
  373. &ego_get_for_subsystem,
  374. handle);
  375. if (NULL == handle->op)
  376. {
  377. handle->response_code = MHD_HTTP_NOT_FOUND;
  378. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
  379. GNUNET_SCHEDULER_add_now (&do_error, handle);
  380. return;
  381. }
  382. }
  383. /**
  384. * Handle identity GET request - responds with all identities
  385. *
  386. * @param con_handle the connection handle
  387. * @param url the url
  388. * @param cls the RequestHandle
  389. */
  390. void
  391. ego_get_all (struct GNUNET_REST_RequestHandle *con_handle,
  392. const char *url,
  393. void *cls)
  394. {
  395. struct RequestHandle *handle = cls;
  396. struct EgoEntry *ego_entry;
  397. struct MHD_Response *resp;
  398. struct GNUNET_HashCode key;
  399. json_t *json_root;
  400. json_t *json_ego;
  401. char *result_str;
  402. char *privkey_str;
  403. json_root = json_array ();
  404. // Return ego/egos
  405. for (ego_entry = handle->ego_head; NULL != ego_entry;
  406. ego_entry = ego_entry->next)
  407. {
  408. json_ego = json_object ();
  409. json_object_set_new (json_ego,
  410. GNUNET_REST_IDENTITY_PARAM_PUBKEY,
  411. json_string (ego_entry->keystring));
  412. GNUNET_CRYPTO_hash ("private", strlen ("private"), &key);
  413. if (GNUNET_YES ==
  414. GNUNET_CONTAINER_multihashmap_contains (
  415. handle->rest_handle->url_param_map, &key))
  416. {
  417. privkey_str = GNUNET_CRYPTO_ecdsa_private_key_to_string (
  418. GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego));
  419. json_object_set_new (json_ego,
  420. GNUNET_REST_IDENTITY_PARAM_PRIVKEY,
  421. json_string (privkey_str));
  422. GNUNET_free (privkey_str);
  423. }
  424. json_object_set_new (json_ego,
  425. GNUNET_REST_IDENTITY_PARAM_NAME,
  426. json_string (ego_entry->identifier));
  427. json_array_append (json_root, json_ego);
  428. json_decref (json_ego);
  429. }
  430. result_str = json_dumps (json_root, 0);
  431. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
  432. resp = GNUNET_REST_create_response (result_str);
  433. MHD_add_response_header (resp, "Content-Type", "application/json");
  434. json_decref (json_root);
  435. handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
  436. GNUNET_free (result_str);
  437. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  438. }
  439. /**
  440. * Responds with the ego_entry identity
  441. *
  442. * @param handle the struct RequestHandle
  443. * @param ego_entry the struct EgoEntry for the response
  444. */
  445. void
  446. ego_get_response (struct RequestHandle *handle, struct EgoEntry *ego_entry)
  447. {
  448. struct MHD_Response *resp;
  449. struct GNUNET_HashCode key;
  450. json_t *json_ego;
  451. char *result_str;
  452. char *privkey_str;
  453. json_ego = json_object ();
  454. json_object_set_new (json_ego,
  455. GNUNET_REST_IDENTITY_PARAM_PUBKEY,
  456. json_string (ego_entry->keystring));
  457. json_object_set_new (json_ego,
  458. GNUNET_REST_IDENTITY_PARAM_NAME,
  459. json_string (ego_entry->identifier));
  460. GNUNET_CRYPTO_hash ("private", strlen ("private"), &key);
  461. if (GNUNET_YES ==
  462. GNUNET_CONTAINER_multihashmap_contains (
  463. handle->rest_handle->url_param_map, &key))
  464. {
  465. privkey_str = GNUNET_CRYPTO_ecdsa_private_key_to_string (
  466. GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego));
  467. json_object_set_new (json_ego,
  468. GNUNET_REST_IDENTITY_PARAM_PRIVKEY,
  469. json_string (privkey_str));
  470. GNUNET_free (privkey_str);
  471. }
  472. result_str = json_dumps (json_ego, 0);
  473. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
  474. resp = GNUNET_REST_create_response (result_str);
  475. handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
  476. MHD_add_response_header (resp, "Content-Type", "application/json");
  477. json_decref (json_ego);
  478. GNUNET_free (result_str);
  479. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  480. }
  481. /**
  482. * Handle identity GET request with a public key
  483. *
  484. * @param con_handle the connection handle
  485. * @param url the url
  486. * @param cls the RequestHandle
  487. */
  488. void
  489. ego_get_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
  490. const char *url,
  491. void *cls)
  492. {
  493. struct RequestHandle *handle = cls;
  494. struct EgoEntry *ego_entry;
  495. char *keystring;
  496. keystring = NULL;
  497. if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
  498. {
  499. handle->response_code = MHD_HTTP_NOT_FOUND;
  500. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_MISSING_PUBKEY);
  501. GNUNET_SCHEDULER_add_now (&do_error, handle);
  502. return;
  503. }
  504. keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
  505. ego_entry = get_egoentry (handle, keystring, NULL);
  506. if (NULL == ego_entry)
  507. {
  508. handle->response_code = MHD_HTTP_NOT_FOUND;
  509. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
  510. GNUNET_SCHEDULER_add_now (&do_error, handle);
  511. return;
  512. }
  513. ego_get_response (handle, ego_entry);
  514. }
  515. /**
  516. * Handle identity GET request with a name
  517. *
  518. * @param con_handle the connection handle
  519. * @param url the url
  520. * @param cls the RequestHandle
  521. */
  522. void
  523. ego_get_name (struct GNUNET_REST_RequestHandle *con_handle,
  524. const char *url,
  525. void *cls)
  526. {
  527. struct RequestHandle *handle = cls;
  528. struct EgoEntry *ego_entry;
  529. char *egoname;
  530. egoname = NULL;
  531. if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
  532. {
  533. handle->response_code = MHD_HTTP_NOT_FOUND;
  534. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_MISSING_NAME);
  535. GNUNET_SCHEDULER_add_now (&do_error, handle);
  536. return;
  537. }
  538. egoname = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
  539. ego_entry = get_egoentry (handle, NULL, egoname);
  540. if (NULL == ego_entry)
  541. {
  542. handle->response_code = MHD_HTTP_NOT_FOUND;
  543. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
  544. GNUNET_SCHEDULER_add_now (&do_error, handle);
  545. return;
  546. }
  547. ego_get_response (handle, ego_entry);
  548. }
  549. /**
  550. * Processing finished
  551. *
  552. * @param cls request handle
  553. * @param emsg error message
  554. */
  555. static void
  556. do_finished (void *cls, const char *emsg)
  557. {
  558. struct RequestHandle *handle = cls;
  559. struct MHD_Response *resp;
  560. handle->op = NULL;
  561. if (NULL != emsg)
  562. {
  563. handle->emsg = GNUNET_strdup (emsg);
  564. GNUNET_SCHEDULER_add_now (&do_error, handle);
  565. return;
  566. }
  567. if (0 == handle->response_code)
  568. {
  569. handle->response_code = MHD_HTTP_NO_CONTENT;
  570. }
  571. resp = GNUNET_REST_create_response (NULL);
  572. handle->proc (handle->proc_cls, resp, handle->response_code);
  573. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  574. }
  575. /**
  576. * Processing finished, when creating an ego.
  577. *
  578. * @param cls request handle
  579. * @param private key of the ego, or NULL on error
  580. * @param emsg error message
  581. */
  582. static void
  583. do_finished_create (void *cls,
  584. const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk,
  585. const char *emsg)
  586. {
  587. struct RequestHandle *handle = cls;
  588. (void) pk;
  589. do_finished (handle, emsg);
  590. }
  591. /**
  592. * Processing edit ego with EgoEntry ego_entry
  593. *
  594. * @param handle the struct RequestHandle
  595. * @param ego_entry the struct EgoEntry we want to edit
  596. */
  597. void
  598. ego_edit (struct RequestHandle *handle, struct EgoEntry *ego_entry)
  599. {
  600. struct EgoEntry *ego_entry_tmp;
  601. struct MHD_Response *resp;
  602. json_t *data_js;
  603. json_error_t err;
  604. char *newname;
  605. char term_data[handle->data_size + 1];
  606. int json_state;
  607. // if no data
  608. if (0 >= handle->data_size)
  609. {
  610. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
  611. GNUNET_SCHEDULER_add_now (&do_error, handle);
  612. return;
  613. }
  614. // if not json
  615. term_data[handle->data_size] = '\0';
  616. GNUNET_memcpy (term_data, handle->data, handle->data_size);
  617. data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
  618. if (NULL == data_js)
  619. {
  620. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
  621. GNUNET_SCHEDULER_add_now (&do_error, handle);
  622. return;
  623. }
  624. newname = NULL;
  625. // NEW NAME
  626. json_state = 0;
  627. json_state = json_unpack (data_js,
  628. "{s:s!}",
  629. GNUNET_REST_IDENTITY_PARAM_NEWNAME,
  630. &newname);
  631. // Change name with pubkey or name identifier
  632. if (0 != json_state)
  633. {
  634. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
  635. GNUNET_SCHEDULER_add_now (&do_error, handle);
  636. json_decref (data_js);
  637. return;
  638. }
  639. if (NULL == newname)
  640. {
  641. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
  642. GNUNET_SCHEDULER_add_now (&do_error, handle);
  643. json_decref (data_js);
  644. return;
  645. }
  646. if (0 >= strlen (newname))
  647. {
  648. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
  649. GNUNET_SCHEDULER_add_now (&do_error, handle);
  650. json_decref (data_js);
  651. return;
  652. }
  653. ego_entry_tmp = get_egoentry (handle, NULL, newname);
  654. if (NULL != ego_entry_tmp)
  655. {
  656. // Ego with same name not allowed (even if its the ego we change)
  657. resp = GNUNET_REST_create_response (NULL);
  658. handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
  659. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  660. json_decref (data_js);
  661. return;
  662. }
  663. handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
  664. ego_entry->identifier,
  665. newname,
  666. &do_finished,
  667. handle);
  668. if (NULL == handle->op)
  669. {
  670. handle->emsg = GNUNET_strdup ("Rename failed");
  671. GNUNET_SCHEDULER_add_now (&do_error, handle);
  672. json_decref (data_js);
  673. return;
  674. }
  675. json_decref (data_js);
  676. return;
  677. }
  678. /**
  679. * Handle identity PUT request with public key
  680. *
  681. * @param con_handle the connection handle
  682. * @param url the url
  683. * @param cls the RequestHandle
  684. */
  685. void
  686. ego_edit_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
  687. const char *url,
  688. void *cls)
  689. {
  690. struct RequestHandle *handle = cls;
  691. struct EgoEntry *ego_entry;
  692. char *keystring;
  693. keystring = NULL;
  694. if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
  695. {
  696. handle->response_code = MHD_HTTP_NOT_FOUND;
  697. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_MISSING_PUBKEY);
  698. GNUNET_SCHEDULER_add_now (&do_error, handle);
  699. return;
  700. }
  701. keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
  702. ego_entry = get_egoentry (handle, keystring, NULL);
  703. if (NULL == ego_entry)
  704. {
  705. handle->response_code = MHD_HTTP_NOT_FOUND;
  706. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
  707. GNUNET_SCHEDULER_add_now (&do_error, handle);
  708. return;
  709. }
  710. ego_edit (handle, ego_entry);
  711. }
  712. /**
  713. * Handle identity PUT request with name
  714. *
  715. * @param con_handle the connection handle
  716. * @param url the url
  717. * @param cls the RequestHandle
  718. */
  719. void
  720. ego_edit_name (struct GNUNET_REST_RequestHandle *con_handle,
  721. const char *url,
  722. void *cls)
  723. {
  724. struct RequestHandle *handle = cls;
  725. struct EgoEntry *ego_entry;
  726. char *name;
  727. name = NULL;
  728. if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
  729. {
  730. handle->response_code = MHD_HTTP_NOT_FOUND;
  731. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_MISSING_NAME);
  732. GNUNET_SCHEDULER_add_now (&do_error, handle);
  733. return;
  734. }
  735. name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
  736. ego_entry = get_egoentry (handle, NULL, name);
  737. if (NULL == ego_entry)
  738. {
  739. handle->response_code = MHD_HTTP_NOT_FOUND;
  740. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
  741. GNUNET_SCHEDULER_add_now (&do_error, handle);
  742. return;
  743. }
  744. ego_edit (handle, ego_entry);
  745. }
  746. /**
  747. * Handle identity subsystem PUT request with name
  748. *
  749. * @param con_handle the connection handle
  750. * @param url the url
  751. * @param cls the RequestHandle
  752. */
  753. void
  754. ego_edit_subsystem (struct GNUNET_REST_RequestHandle *con_handle,
  755. const char *url,
  756. void *cls)
  757. {
  758. struct RequestHandle *handle = cls;
  759. struct EgoEntry *ego_entry;
  760. json_t *data_js;
  761. json_error_t err;
  762. char *newsubsys;
  763. char *name;
  764. char term_data[handle->data_size + 1];
  765. int json_state;
  766. name = NULL;
  767. if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
  768. {
  769. handle->response_code = MHD_HTTP_NOT_FOUND;
  770. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_MISSING_NAME);
  771. GNUNET_SCHEDULER_add_now (&do_error, handle);
  772. return;
  773. }
  774. name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
  775. ego_entry = get_egoentry (handle, NULL, name);
  776. if (NULL == ego_entry)
  777. {
  778. handle->response_code = MHD_HTTP_NOT_FOUND;
  779. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
  780. GNUNET_SCHEDULER_add_now (&do_error, handle);
  781. return;
  782. }
  783. // if no data
  784. if (0 >= handle->data_size)
  785. {
  786. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
  787. GNUNET_SCHEDULER_add_now (&do_error, handle);
  788. return;
  789. }
  790. // if not json
  791. term_data[handle->data_size] = '\0';
  792. GNUNET_memcpy (term_data, handle->data, handle->data_size);
  793. data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
  794. if (NULL == data_js)
  795. {
  796. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
  797. GNUNET_SCHEDULER_add_now (&do_error, handle);
  798. return;
  799. }
  800. newsubsys = NULL;
  801. // SUBSYSTEM
  802. json_state = 0;
  803. json_state = json_unpack (data_js,
  804. "{s:s!}",
  805. GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM,
  806. &newsubsys);
  807. // Change subsystem with pubkey or name identifier
  808. if (0 != json_state)
  809. {
  810. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
  811. GNUNET_SCHEDULER_add_now (&do_error, handle);
  812. json_decref (data_js);
  813. return;
  814. }
  815. if (NULL == newsubsys)
  816. {
  817. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
  818. GNUNET_SCHEDULER_add_now (&do_error, handle);
  819. json_decref (data_js);
  820. return;
  821. }
  822. if (0 >= strlen (newsubsys))
  823. {
  824. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
  825. GNUNET_SCHEDULER_add_now (&do_error, handle);
  826. json_decref (data_js);
  827. return;
  828. }
  829. handle->response_code = MHD_HTTP_NO_CONTENT;
  830. handle->op = GNUNET_IDENTITY_set (handle->identity_handle,
  831. newsubsys,
  832. ego_entry->ego,
  833. &do_finished,
  834. handle);
  835. if (NULL == handle->op)
  836. {
  837. handle->emsg = GNUNET_strdup ("Setting subsystem failed");
  838. GNUNET_SCHEDULER_add_now (&do_error, handle);
  839. return;
  840. }
  841. json_decref (data_js);
  842. return;
  843. }
  844. /**
  845. * Handle identity POST request
  846. *
  847. * @param con_handle the connection handle
  848. * @param url the url
  849. * @param cls the RequestHandle
  850. */
  851. void
  852. ego_create (struct GNUNET_REST_RequestHandle *con_handle,
  853. const char *url,
  854. void *cls)
  855. {
  856. struct RequestHandle *handle = cls;
  857. struct EgoEntry *ego_entry;
  858. struct MHD_Response *resp;
  859. json_t *data_js;
  860. json_error_t err;
  861. char *egoname;
  862. char *privkey;
  863. struct GNUNET_CRYPTO_EcdsaPrivateKey pk;
  864. struct GNUNET_CRYPTO_EcdsaPrivateKey *pk_ptr;
  865. int json_unpack_state;
  866. char term_data[handle->data_size + 1];
  867. if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
  868. {
  869. GNUNET_SCHEDULER_add_now (&do_error, handle);
  870. return;
  871. }
  872. if (0 >= handle->data_size)
  873. {
  874. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
  875. GNUNET_SCHEDULER_add_now (&do_error, handle);
  876. return;
  877. }
  878. term_data[handle->data_size] = '\0';
  879. GNUNET_memcpy (term_data, handle->data, handle->data_size);
  880. data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
  881. if (NULL == data_js)
  882. {
  883. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
  884. GNUNET_SCHEDULER_add_now (&do_error, handle);
  885. json_decref (data_js);
  886. return;
  887. }
  888. json_unpack_state = 0;
  889. privkey = NULL;
  890. json_unpack_state =
  891. json_unpack (data_js, "{s:s, s?:s!}",
  892. GNUNET_REST_IDENTITY_PARAM_NAME, &egoname,
  893. GNUNET_REST_IDENTITY_PARAM_PRIVKEY, &privkey);
  894. if (0 != json_unpack_state)
  895. {
  896. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
  897. GNUNET_SCHEDULER_add_now (&do_error, handle);
  898. json_decref (data_js);
  899. return;
  900. }
  901. if (NULL == egoname)
  902. {
  903. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
  904. GNUNET_SCHEDULER_add_now (&do_error, handle);
  905. json_decref (data_js);
  906. return;
  907. }
  908. if (0 >= strlen (egoname))
  909. {
  910. json_decref (data_js);
  911. handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
  912. GNUNET_SCHEDULER_add_now (&do_error, handle);
  913. return;
  914. }
  915. GNUNET_STRINGS_utf8_tolower (egoname, egoname);
  916. for (ego_entry = handle->ego_head; NULL != ego_entry;
  917. ego_entry = ego_entry->next)
  918. {
  919. if (0 == strcasecmp (egoname, ego_entry->identifier))
  920. {
  921. resp = GNUNET_REST_create_response (NULL);
  922. handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
  923. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  924. json_decref (data_js);
  925. return;
  926. }
  927. }
  928. handle->name = GNUNET_strdup (egoname);
  929. if (NULL != privkey)
  930. {
  931. GNUNET_STRINGS_string_to_data (privkey,
  932. strlen (privkey),
  933. &pk,
  934. sizeof(struct
  935. GNUNET_CRYPTO_EcdsaPrivateKey));
  936. pk_ptr = &pk;
  937. }
  938. else
  939. pk_ptr = NULL;
  940. json_decref (data_js);
  941. handle->response_code = MHD_HTTP_CREATED;
  942. handle->op = GNUNET_IDENTITY_create (handle->identity_handle,
  943. handle->name,
  944. pk_ptr,
  945. &do_finished_create,
  946. handle);
  947. }
  948. /**
  949. * Handle identity DELETE request with public key
  950. *
  951. * @param con_handle the connection handle
  952. * @param url the url
  953. * @param cls the RequestHandle
  954. */
  955. void
  956. ego_delete_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
  957. const char *url,
  958. void *cls)
  959. {
  960. struct RequestHandle *handle = cls;
  961. struct EgoEntry *ego_entry;
  962. char *keystring;
  963. keystring = NULL;
  964. if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
  965. {
  966. handle->response_code = MHD_HTTP_NOT_FOUND;
  967. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_MISSING_PUBKEY);
  968. GNUNET_SCHEDULER_add_now (&do_error, handle);
  969. return;
  970. }
  971. keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
  972. ego_entry = get_egoentry (handle, keystring, NULL);
  973. if (NULL == ego_entry)
  974. {
  975. handle->response_code = MHD_HTTP_NOT_FOUND;
  976. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
  977. GNUNET_SCHEDULER_add_now (&do_error, handle);
  978. return;
  979. }
  980. handle->response_code = MHD_HTTP_NO_CONTENT;
  981. handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
  982. ego_entry->identifier,
  983. &do_finished,
  984. handle);
  985. }
  986. /**
  987. * Handle identity DELETE request with name
  988. *
  989. * @param con_handle the connection handle
  990. * @param url the url
  991. * @param cls the RequestHandle
  992. */
  993. void
  994. ego_delete_name (struct GNUNET_REST_RequestHandle *con_handle,
  995. const char *url,
  996. void *cls)
  997. {
  998. struct RequestHandle *handle = cls;
  999. struct EgoEntry *ego_entry;
  1000. char *name;
  1001. name = NULL;
  1002. if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
  1003. {
  1004. handle->response_code = MHD_HTTP_NOT_FOUND;
  1005. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_MISSING_NAME);
  1006. GNUNET_SCHEDULER_add_now (&do_error, handle);
  1007. return;
  1008. }
  1009. name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
  1010. ego_entry = get_egoentry (handle, NULL, name);
  1011. if (NULL == ego_entry)
  1012. {
  1013. handle->response_code = MHD_HTTP_NOT_FOUND;
  1014. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
  1015. GNUNET_SCHEDULER_add_now (&do_error, handle);
  1016. return;
  1017. }
  1018. handle->response_code = MHD_HTTP_NO_CONTENT;
  1019. handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
  1020. ego_entry->identifier,
  1021. &do_finished,
  1022. handle);
  1023. }
  1024. /**
  1025. * Respond to OPTIONS request
  1026. *
  1027. * @param con_handle the connection handle
  1028. * @param url the url
  1029. * @param cls the RequestHandle
  1030. */
  1031. static void
  1032. options_cont (struct GNUNET_REST_RequestHandle *con_handle,
  1033. const char *url,
  1034. void *cls)
  1035. {
  1036. struct MHD_Response *resp;
  1037. struct RequestHandle *handle = cls;
  1038. // For now, independent of path return all options
  1039. resp = GNUNET_REST_create_response (NULL);
  1040. MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
  1041. handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
  1042. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  1043. return;
  1044. }
  1045. /**
  1046. * Handle rest request
  1047. *
  1048. * @param handle the request handle
  1049. */
  1050. static void
  1051. init_cont (struct RequestHandle *handle)
  1052. {
  1053. struct GNUNET_REST_RequestHandlerError err;
  1054. static const struct GNUNET_REST_RequestHandler handlers[] =
  1055. { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get_all },
  1056. { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY,
  1057. &ego_get_pubkey },
  1058. { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name },
  1059. { MHD_HTTP_METHOD_GET,
  1060. GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM,
  1061. &ego_get_subsystem },
  1062. { MHD_HTTP_METHOD_PUT,
  1063. GNUNET_REST_API_NS_IDENTITY_PUBKEY,
  1064. &ego_edit_pubkey },
  1065. { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name },
  1066. { MHD_HTTP_METHOD_PUT,
  1067. GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM,
  1068. &ego_edit_subsystem },
  1069. { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
  1070. { MHD_HTTP_METHOD_DELETE,
  1071. GNUNET_REST_API_NS_IDENTITY_PUBKEY,
  1072. &ego_delete_pubkey },
  1073. { MHD_HTTP_METHOD_DELETE,
  1074. GNUNET_REST_API_NS_IDENTITY_NAME,
  1075. &ego_delete_name },
  1076. { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
  1077. GNUNET_REST_HANDLER_END };
  1078. if (GNUNET_NO ==
  1079. GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
  1080. {
  1081. handle->response_code = err.error_code;
  1082. GNUNET_SCHEDULER_add_now (&do_error, handle);
  1083. }
  1084. }
  1085. /**
  1086. * If listing is enabled, prints information about the egos.
  1087. *
  1088. * This function is initially called for all egos and then again
  1089. * whenever a ego's identifier changes or if it is deleted. At the
  1090. * end of the initial pass over all egos, the function is once called
  1091. * with 'NULL' for 'ego'. That does NOT mean that the callback won't
  1092. * be invoked in the future or that there was an error.
  1093. *
  1094. * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
  1095. * this function is only called ONCE, and 'NULL' being passed in
  1096. * 'ego' does indicate an error (i.e. name is taken or no default
  1097. * value is known). If 'ego' is non-NULL and if '*ctx'
  1098. * is set in those callbacks, the value WILL be passed to a subsequent
  1099. * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
  1100. * that one was not NULL).
  1101. *
  1102. * When an identity is renamed, this function is called with the
  1103. * (known) ego but the NEW identifier.
  1104. *
  1105. * When an identity is deleted, this function is called with the
  1106. * (known) ego and "NULL" for the 'identifier'. In this case,
  1107. * the 'ego' is henceforth invalid (and the 'ctx' should also be
  1108. * cleaned up).
  1109. *
  1110. * @param cls closure
  1111. * @param ego ego handle
  1112. * @param ctx context for application to store data for this ego
  1113. * (during the lifetime of this process, initially NULL)
  1114. * @param identifier identifier assigned by the user for this ego,
  1115. * NULL if the user just deleted the ego and it
  1116. * must thus no longer be used
  1117. */
  1118. static void
  1119. init_egos (void *cls,
  1120. struct GNUNET_IDENTITY_Ego *ego,
  1121. void **ctx,
  1122. const char *identifier)
  1123. {
  1124. struct RequestHandle *handle = cls;
  1125. struct EgoEntry *ego_entry;
  1126. struct GNUNET_CRYPTO_EcdsaPublicKey pk;
  1127. if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
  1128. {
  1129. handle->state = ID_REST_STATE_POST_INIT;
  1130. init_cont (handle);
  1131. return;
  1132. }
  1133. if (ID_REST_STATE_INIT == handle->state)
  1134. {
  1135. ego_entry = GNUNET_new (struct EgoEntry);
  1136. GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
  1137. ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
  1138. ego_entry->ego = ego;
  1139. ego_entry->identifier = GNUNET_strdup (identifier);
  1140. GNUNET_CONTAINER_DLL_insert_tail (handle->ego_head,
  1141. handle->ego_tail,
  1142. ego_entry);
  1143. return;
  1144. }
  1145. // Check if ego exists
  1146. for (ego_entry = handle->ego_head; NULL != ego_entry;)
  1147. {
  1148. struct EgoEntry *tmp = ego_entry;
  1149. ego_entry = ego_entry->next;
  1150. if (ego != tmp->ego)
  1151. continue;
  1152. // Deleted
  1153. if (NULL == identifier)
  1154. {
  1155. GNUNET_CONTAINER_DLL_remove (handle->ego_head,
  1156. handle->ego_tail,
  1157. tmp);
  1158. GNUNET_free (tmp->keystring);
  1159. GNUNET_free (tmp->identifier);
  1160. GNUNET_free (tmp);
  1161. }
  1162. else
  1163. {
  1164. // Renamed
  1165. GNUNET_free (tmp->identifier);
  1166. tmp->identifier = GNUNET_strdup (identifier);
  1167. }
  1168. return;
  1169. }
  1170. // New ego
  1171. ego_entry = GNUNET_new (struct EgoEntry);
  1172. GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
  1173. ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
  1174. ego_entry->ego = ego;
  1175. GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
  1176. GNUNET_CONTAINER_DLL_insert_tail (handle->ego_head,
  1177. handle->ego_tail,
  1178. ego_entry);
  1179. }
  1180. /**
  1181. * Function processing the REST call
  1182. *
  1183. * @param method HTTP method
  1184. * @param url URL of the HTTP request
  1185. * @param data body of the HTTP request (optional)
  1186. * @param data_size length of the body
  1187. * @param proc callback function for the result
  1188. * @param proc_cls closure for callback function
  1189. * @return GNUNET_OK if request accepted
  1190. */
  1191. static void
  1192. rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
  1193. GNUNET_REST_ResultProcessor proc,
  1194. void *proc_cls)
  1195. {
  1196. struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
  1197. handle->response_code = 0;
  1198. handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
  1199. handle->proc_cls = proc_cls;
  1200. handle->proc = proc;
  1201. handle->rest_handle = rest_handle;
  1202. handle->data = rest_handle->data;
  1203. handle->data_size = rest_handle->data_size;
  1204. handle->url = GNUNET_strdup (rest_handle->url);
  1205. if (handle->url[strlen (handle->url) - 1] == '/')
  1206. handle->url[strlen (handle->url) - 1] = '\0';
  1207. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
  1208. handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &init_egos, handle);
  1209. handle->timeout_task =
  1210. GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
  1211. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
  1212. }
  1213. /**
  1214. * Entry point for the plugin.
  1215. *
  1216. * @param cls Config info
  1217. * @return NULL on error, otherwise the plugin context
  1218. */
  1219. void *
  1220. libgnunet_plugin_rest_identity_init (void *cls)
  1221. {
  1222. static struct Plugin plugin;
  1223. struct GNUNET_REST_Plugin *api;
  1224. cfg = cls;
  1225. if (NULL != plugin.cfg)
  1226. return NULL; /* can only initialize once! */
  1227. memset (&plugin, 0, sizeof(struct Plugin));
  1228. plugin.cfg = cfg;
  1229. api = GNUNET_new (struct GNUNET_REST_Plugin);
  1230. api->cls = &plugin;
  1231. api->name = GNUNET_REST_API_NS_IDENTITY;
  1232. api->process_request = &rest_process_request;
  1233. GNUNET_asprintf (&allow_methods,
  1234. "%s, %s, %s, %s, %s",
  1235. MHD_HTTP_METHOD_GET,
  1236. MHD_HTTP_METHOD_POST,
  1237. MHD_HTTP_METHOD_PUT,
  1238. MHD_HTTP_METHOD_DELETE,
  1239. MHD_HTTP_METHOD_OPTIONS);
  1240. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Identity REST API initialized\n"));
  1241. return api;
  1242. }
  1243. /**
  1244. * Exit point from the plugin.
  1245. *
  1246. * @param cls the plugin context (as returned by "init")
  1247. * @return always NULL
  1248. */
  1249. void *
  1250. libgnunet_plugin_rest_identity_done (void *cls)
  1251. {
  1252. struct GNUNET_REST_Plugin *api = cls;
  1253. struct Plugin *plugin = api->cls;
  1254. plugin->cfg = NULL;
  1255. GNUNET_free (allow_methods);
  1256. GNUNET_free (api);
  1257. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n");
  1258. return NULL;
  1259. }
  1260. /* end of plugin_rest_identity.c */