plugin_rest_identity.c 37 KB

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