identity_api.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2013, 2016 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file identity/identity_api.c
  18. * @brief api to interact with the identity service
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_constants.h"
  24. #include "gnunet_protocols.h"
  25. #include "gnunet_identity_service.h"
  26. #include "identity.h"
  27. #define LOG(kind, ...) GNUNET_log_from (kind, "identity-api", __VA_ARGS__)
  28. /**
  29. * Handle for an operation with the identity service.
  30. */
  31. struct GNUNET_IDENTITY_Operation
  32. {
  33. /**
  34. * Main identity handle.
  35. */
  36. struct GNUNET_IDENTITY_Handle *h;
  37. /**
  38. * We keep operations in a DLL.
  39. */
  40. struct GNUNET_IDENTITY_Operation *next;
  41. /**
  42. * We keep operations in a DLL.
  43. */
  44. struct GNUNET_IDENTITY_Operation *prev;
  45. /**
  46. * Message to send to the identity service.
  47. * Allocated at the end of this struct.
  48. */
  49. const struct GNUNET_MessageHeader *msg;
  50. /**
  51. * Continuation to invoke with the result of the transmission; @e cb
  52. * and @e create_cont will be NULL in this case.
  53. */
  54. GNUNET_IDENTITY_Continuation cont;
  55. /**
  56. * Continuation to invoke with the result of the transmission; @e cb
  57. * and @a cb will be NULL in this case.
  58. */
  59. GNUNET_IDENTITY_CreateContinuation create_cont;
  60. /**
  61. * Private key to return to @e create_cont, or NULL.
  62. */
  63. struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
  64. /**
  65. * Continuation to invoke with the result of the transmission for
  66. * 'get' operations (@e cont and @a create_cont will be NULL in this case).
  67. */
  68. GNUNET_IDENTITY_Callback cb;
  69. /**
  70. * Closure for @e cont or @e cb.
  71. */
  72. void *cls;
  73. };
  74. /**
  75. * Handle for the service.
  76. */
  77. struct GNUNET_IDENTITY_Handle
  78. {
  79. /**
  80. * Configuration to use.
  81. */
  82. const struct GNUNET_CONFIGURATION_Handle *cfg;
  83. /**
  84. * Connection to service.
  85. */
  86. struct GNUNET_MQ_Handle *mq;
  87. /**
  88. * Hash map from the hash of the public key to the
  89. * respective `GNUNET_IDENTITY_Ego` handle.
  90. */
  91. struct GNUNET_CONTAINER_MultiHashMap *egos;
  92. /**
  93. * Function to call when we receive updates.
  94. */
  95. GNUNET_IDENTITY_Callback cb;
  96. /**
  97. * Closure for @e cb.
  98. */
  99. void *cb_cls;
  100. /**
  101. * Head of active operations.
  102. */
  103. struct GNUNET_IDENTITY_Operation *op_head;
  104. /**
  105. * Tail of active operations.
  106. */
  107. struct GNUNET_IDENTITY_Operation *op_tail;
  108. /**
  109. * Task doing exponential back-off trying to reconnect.
  110. */
  111. struct GNUNET_SCHEDULER_Task *reconnect_task;
  112. /**
  113. * Time for next connect retry.
  114. */
  115. struct GNUNET_TIME_Relative reconnect_delay;
  116. /**
  117. * Are we polling for incoming messages right now?
  118. */
  119. int in_receive;
  120. };
  121. /**
  122. * Obtain the ego representing 'anonymous' users.
  123. *
  124. * @return handle for the anonymous user, must not be freed
  125. */
  126. const struct GNUNET_IDENTITY_Ego *
  127. GNUNET_IDENTITY_ego_get_anonymous ()
  128. {
  129. static struct GNUNET_IDENTITY_Ego anon;
  130. struct GNUNET_CRYPTO_EcdsaPublicKey pub;
  131. if (NULL != anon.pk)
  132. return &anon;
  133. anon.pk = (struct GNUNET_CRYPTO_EcdsaPrivateKey *)
  134. GNUNET_CRYPTO_ecdsa_key_get_anonymous ();
  135. GNUNET_CRYPTO_ecdsa_key_get_public (anon.pk, &pub);
  136. GNUNET_CRYPTO_hash (&pub, sizeof (pub), &anon.id);
  137. return &anon;
  138. }
  139. /**
  140. * Try again to connect to the identity service.
  141. *
  142. * @param cls handle to the identity service.
  143. */
  144. static void
  145. reconnect (void *cls);
  146. /**
  147. * Free ego from hash map.
  148. *
  149. * @param cls identity service handle
  150. * @param key unused
  151. * @param value ego to free
  152. * @return #GNUNET_OK (continue to iterate)
  153. */
  154. static int
  155. free_ego (void *cls, const struct GNUNET_HashCode *key, void *value)
  156. {
  157. struct GNUNET_IDENTITY_Handle *h = cls;
  158. struct GNUNET_IDENTITY_Ego *ego = value;
  159. if (NULL != h->cb)
  160. h->cb (h->cb_cls, ego, &ego->ctx, NULL);
  161. GNUNET_free (ego->pk);
  162. GNUNET_free (ego->name);
  163. GNUNET_assert (GNUNET_YES ==
  164. GNUNET_CONTAINER_multihashmap_remove (h->egos, key, value));
  165. GNUNET_free (ego);
  166. return GNUNET_OK;
  167. }
  168. /**
  169. * Reschedule a connect attempt to the service.
  170. *
  171. * @param h transport service to reconnect
  172. */
  173. static void
  174. reschedule_connect (struct GNUNET_IDENTITY_Handle *h)
  175. {
  176. struct GNUNET_IDENTITY_Operation *op;
  177. GNUNET_assert (NULL == h->reconnect_task);
  178. if (NULL != h->mq)
  179. {
  180. GNUNET_MQ_destroy (h->mq);
  181. h->mq = NULL;
  182. }
  183. while (NULL != (op = h->op_head))
  184. {
  185. GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
  186. if (NULL != op->cont)
  187. op->cont (op->cls, "Error in communication with the identity service");
  188. else if (NULL != op->cb)
  189. op->cb (op->cls, NULL, NULL, NULL);
  190. else if (NULL != op->create_cont)
  191. op->create_cont (op->cls,
  192. NULL,
  193. "Failed to communicate with the identity service");
  194. GNUNET_free_non_null (op->pk);
  195. GNUNET_free (op);
  196. }
  197. GNUNET_CONTAINER_multihashmap_iterate (h->egos, &free_ego, h);
  198. LOG (GNUNET_ERROR_TYPE_DEBUG,
  199. "Scheduling task to reconnect to identity service in %s.\n",
  200. GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay, GNUNET_YES));
  201. h->reconnect_task =
  202. GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h);
  203. h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
  204. }
  205. /**
  206. * Generic error handler, called with the appropriate error code and
  207. * the same closure specified at the creation of the message queue.
  208. * Not every message queue implementation supports an error handler.
  209. *
  210. * @param cls closure with the `struct GNUNET_IDENTITY_Handle *`
  211. * @param error error code
  212. */
  213. static void
  214. mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
  215. {
  216. struct GNUNET_IDENTITY_Handle *h = cls;
  217. reschedule_connect (h);
  218. }
  219. /**
  220. * We received a result code from the service. Check the message
  221. * is well-formed.
  222. *
  223. * @param cls closure
  224. * @param rcm result message received
  225. * @return #GNUNET_OK if the message is well-formed
  226. */
  227. static int
  228. check_identity_result_code (void *cls, const struct ResultCodeMessage *rcm)
  229. {
  230. if (sizeof (*rcm) != htons (rcm->header.size))
  231. GNUNET_MQ_check_zero_termination (rcm);
  232. return GNUNET_OK;
  233. }
  234. /**
  235. * We received a result code from the service.
  236. *
  237. * @param cls closure
  238. * @param rcm result message received
  239. */
  240. static void
  241. handle_identity_result_code (void *cls, const struct ResultCodeMessage *rcm)
  242. {
  243. struct GNUNET_IDENTITY_Handle *h = cls;
  244. struct GNUNET_IDENTITY_Operation *op;
  245. uint16_t size = ntohs (rcm->header.size) - sizeof (*rcm);
  246. const char *str = (0 == size) ? NULL : (const char *) &rcm[1];
  247. op = h->op_head;
  248. if (NULL == op)
  249. {
  250. GNUNET_break (0);
  251. reschedule_connect (h);
  252. return;
  253. }
  254. GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
  255. if (NULL != op->cont)
  256. op->cont (op->cls, str);
  257. else if (NULL != op->cb)
  258. op->cb (op->cls, NULL, NULL, NULL);
  259. else if (NULL != op->create_cont)
  260. op->create_cont (op->cls, (NULL == str) ? op->pk : NULL, str);
  261. GNUNET_free_non_null (op->pk);
  262. GNUNET_free (op);
  263. }
  264. /**
  265. * Check validity of identity update message.
  266. *
  267. * @param cls closure
  268. * @param um message received
  269. * @return #GNUNET_OK if the message is well-formed
  270. */
  271. static int
  272. check_identity_update (void *cls, const struct UpdateMessage *um)
  273. {
  274. uint16_t size = ntohs (um->header.size);
  275. uint16_t name_len = ntohs (um->name_len);
  276. const char *str = (const char *) &um[1];
  277. if ((size != name_len + sizeof (struct UpdateMessage)) ||
  278. ((0 != name_len) && ('\0' != str[name_len - 1])))
  279. {
  280. GNUNET_break (0);
  281. return GNUNET_SYSERR;
  282. }
  283. return GNUNET_OK;
  284. }
  285. /**
  286. * Handle identity update message.
  287. *
  288. * @param cls closure
  289. * @param um message received
  290. */
  291. static void
  292. handle_identity_update (void *cls, const struct UpdateMessage *um)
  293. {
  294. struct GNUNET_IDENTITY_Handle *h = cls;
  295. uint16_t name_len = ntohs (um->name_len);
  296. const char *str = (0 == name_len) ? NULL : (const char *) &um[1];
  297. struct GNUNET_CRYPTO_EcdsaPublicKey pub;
  298. struct GNUNET_HashCode id;
  299. struct GNUNET_IDENTITY_Ego *ego;
  300. if (GNUNET_YES == ntohs (um->end_of_list))
  301. {
  302. /* end of initial list of data */
  303. if (NULL != h->cb)
  304. h->cb (h->cb_cls, NULL, NULL, NULL);
  305. return;
  306. }
  307. GNUNET_CRYPTO_ecdsa_key_get_public (&um->private_key, &pub);
  308. GNUNET_CRYPTO_hash (&pub, sizeof (pub), &id);
  309. ego = GNUNET_CONTAINER_multihashmap_get (h->egos, &id);
  310. if (NULL == ego)
  311. {
  312. /* ego was created */
  313. if (NULL == str)
  314. {
  315. /* deletion of unknown ego? not allowed */
  316. GNUNET_break (0);
  317. reschedule_connect (h);
  318. return;
  319. }
  320. ego = GNUNET_new (struct GNUNET_IDENTITY_Ego);
  321. ego->pk = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
  322. *ego->pk = um->private_key;
  323. ego->name = GNUNET_strdup (str);
  324. ego->id = id;
  325. GNUNET_assert (GNUNET_YES ==
  326. GNUNET_CONTAINER_multihashmap_put (
  327. h->egos,
  328. &ego->id,
  329. ego,
  330. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  331. }
  332. if (NULL == str)
  333. {
  334. /* ego was deleted */
  335. GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (h->egos,
  336. &ego->id,
  337. ego));
  338. }
  339. else
  340. {
  341. /* ego changed name */
  342. GNUNET_free (ego->name);
  343. ego->name = GNUNET_strdup (str);
  344. }
  345. /* inform application about change */
  346. if (NULL != h->cb)
  347. h->cb (h->cb_cls, ego, &ego->ctx, str);
  348. /* complete deletion */
  349. if (NULL == str)
  350. {
  351. GNUNET_free (ego->pk);
  352. GNUNET_free (ego->name);
  353. GNUNET_free (ego);
  354. }
  355. }
  356. /**
  357. * Function called when we receive a set default message from the
  358. * service.
  359. *
  360. * @param cls closure
  361. * @param sdm message received
  362. * @return #GNUNET_OK if the message is well-formed
  363. */
  364. static int
  365. check_identity_set_default (void *cls, const struct SetDefaultMessage *sdm)
  366. {
  367. uint16_t size = ntohs (sdm->header.size) - sizeof (*sdm);
  368. uint16_t name_len = ntohs (sdm->name_len);
  369. const char *str = (const char *) &sdm[1];
  370. if ((size != name_len) || ((0 != name_len) && ('\0' != str[name_len - 1])))
  371. {
  372. GNUNET_break (0);
  373. return GNUNET_SYSERR;
  374. }
  375. GNUNET_break (0 == ntohs (sdm->reserved));
  376. return GNUNET_OK;
  377. }
  378. /**
  379. * Type of a function to call when we receive a message
  380. * from the service.
  381. *
  382. * @param cls closure
  383. * @param sdm message received
  384. */
  385. static void
  386. handle_identity_set_default (void *cls, const struct SetDefaultMessage *sdm)
  387. {
  388. struct GNUNET_IDENTITY_Handle *h = cls;
  389. struct GNUNET_IDENTITY_Operation *op;
  390. struct GNUNET_CRYPTO_EcdsaPublicKey pub;
  391. struct GNUNET_HashCode id;
  392. struct GNUNET_IDENTITY_Ego *ego;
  393. GNUNET_CRYPTO_ecdsa_key_get_public (&sdm->private_key, &pub);
  394. GNUNET_CRYPTO_hash (&pub, sizeof (pub), &id);
  395. ego = GNUNET_CONTAINER_multihashmap_get (h->egos, &id);
  396. if (NULL == ego)
  397. {
  398. GNUNET_break (0);
  399. reschedule_connect (h);
  400. return;
  401. }
  402. op = h->op_head;
  403. if (NULL == op)
  404. {
  405. GNUNET_break (0);
  406. reschedule_connect (h);
  407. return;
  408. }
  409. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  410. "Received SET_DEFAULT message from identity service\n");
  411. GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
  412. if (NULL != op->cb)
  413. op->cb (op->cls, ego, &ego->ctx, ego->name);
  414. GNUNET_free (op);
  415. }
  416. /**
  417. * Try again to connect to the identity service.
  418. *
  419. * @param cls handle to the identity service.
  420. */
  421. static void
  422. reconnect (void *cls)
  423. {
  424. struct GNUNET_IDENTITY_Handle *h = cls;
  425. struct GNUNET_MQ_MessageHandler handlers[] =
  426. {GNUNET_MQ_hd_var_size (identity_result_code,
  427. GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE,
  428. struct ResultCodeMessage,
  429. h),
  430. GNUNET_MQ_hd_var_size (identity_update,
  431. GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE,
  432. struct UpdateMessage,
  433. h),
  434. GNUNET_MQ_hd_var_size (identity_set_default,
  435. GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT,
  436. struct SetDefaultMessage,
  437. h),
  438. GNUNET_MQ_handler_end ()};
  439. struct GNUNET_MQ_Envelope *env;
  440. struct GNUNET_MessageHeader *msg;
  441. h->reconnect_task = NULL;
  442. LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to identity service.\n");
  443. GNUNET_assert (NULL == h->mq);
  444. h->mq =
  445. GNUNET_CLIENT_connect (h->cfg, "identity", handlers, &mq_error_handler, h);
  446. if (NULL == h->mq)
  447. return;
  448. if (NULL != h->cb)
  449. {
  450. env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_IDENTITY_START);
  451. GNUNET_MQ_send (h->mq, env);
  452. }
  453. }
  454. /**
  455. * Connect to the identity service.
  456. *
  457. * @param cfg the configuration to use
  458. * @param cb function to call on all identity events, can be NULL
  459. * @param cb_cls closure for @a cb
  460. * @return handle to use
  461. */
  462. struct GNUNET_IDENTITY_Handle *
  463. GNUNET_IDENTITY_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
  464. GNUNET_IDENTITY_Callback cb,
  465. void *cb_cls)
  466. {
  467. struct GNUNET_IDENTITY_Handle *h;
  468. h = GNUNET_new (struct GNUNET_IDENTITY_Handle);
  469. h->cfg = cfg;
  470. h->cb = cb;
  471. h->cb_cls = cb_cls;
  472. h->egos = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_YES);
  473. reconnect (h);
  474. if (NULL == h->mq)
  475. {
  476. GNUNET_free (h);
  477. return NULL;
  478. }
  479. return h;
  480. }
  481. /**
  482. * Obtain the ECC key associated with a ego.
  483. *
  484. * @param ego the ego
  485. * @return associated ECC key, valid as long as the ego is valid
  486. */
  487. const struct GNUNET_CRYPTO_EcdsaPrivateKey *
  488. GNUNET_IDENTITY_ego_get_private_key (const struct GNUNET_IDENTITY_Ego *ego)
  489. {
  490. return ego->pk;
  491. }
  492. /**
  493. * Get the identifier (public key) of an ego.
  494. *
  495. * @param ego identity handle with the private key
  496. * @param pk set to ego's public key
  497. */
  498. void
  499. GNUNET_IDENTITY_ego_get_public_key (const struct GNUNET_IDENTITY_Ego *ego,
  500. struct GNUNET_CRYPTO_EcdsaPublicKey *pk)
  501. {
  502. GNUNET_CRYPTO_ecdsa_key_get_public (ego->pk, pk);
  503. }
  504. /**
  505. * Obtain the identity that is currently preferred/default
  506. * for a service.
  507. *
  508. * @param h identity service to query
  509. * @param service_name for which service is an identity wanted
  510. * @param cb function to call with the result (will only be called once)
  511. * @param cb_cls closure for @a cb
  512. * @return handle to abort the operation
  513. */
  514. struct GNUNET_IDENTITY_Operation *
  515. GNUNET_IDENTITY_get (struct GNUNET_IDENTITY_Handle *h,
  516. const char *service_name,
  517. GNUNET_IDENTITY_Callback cb,
  518. void *cb_cls)
  519. {
  520. struct GNUNET_IDENTITY_Operation *op;
  521. struct GNUNET_MQ_Envelope *env;
  522. struct GetDefaultMessage *gdm;
  523. size_t slen;
  524. if (NULL == h->mq)
  525. return NULL;
  526. GNUNET_assert (NULL != h->cb);
  527. slen = strlen (service_name) + 1;
  528. if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct GetDefaultMessage))
  529. {
  530. GNUNET_break (0);
  531. return NULL;
  532. }
  533. op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
  534. op->h = h;
  535. op->cb = cb;
  536. op->cls = cb_cls;
  537. GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
  538. env =
  539. GNUNET_MQ_msg_extra (gdm, slen, GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT);
  540. gdm->name_len = htons (slen);
  541. gdm->reserved = htons (0);
  542. GNUNET_memcpy (&gdm[1], service_name, slen);
  543. GNUNET_MQ_send (h->mq, env);
  544. return op;
  545. }
  546. /**
  547. * Set the preferred/default identity for a service.
  548. *
  549. * @param h identity service to inform
  550. * @param service_name for which service is an identity set
  551. * @param ego new default identity to be set for this service
  552. * @param cont function to call once the operation finished
  553. * @param cont_cls closure for @a cont
  554. * @return handle to abort the operation
  555. */
  556. struct GNUNET_IDENTITY_Operation *
  557. GNUNET_IDENTITY_set (struct GNUNET_IDENTITY_Handle *h,
  558. const char *service_name,
  559. struct GNUNET_IDENTITY_Ego *ego,
  560. GNUNET_IDENTITY_Continuation cont,
  561. void *cont_cls)
  562. {
  563. struct GNUNET_IDENTITY_Operation *op;
  564. struct GNUNET_MQ_Envelope *env;
  565. struct SetDefaultMessage *sdm;
  566. size_t slen;
  567. if (NULL == h->mq)
  568. return NULL;
  569. GNUNET_assert (NULL != h->cb);
  570. slen = strlen (service_name) + 1;
  571. if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct SetDefaultMessage))
  572. {
  573. GNUNET_break (0);
  574. return NULL;
  575. }
  576. op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
  577. op->h = h;
  578. op->cont = cont;
  579. op->cls = cont_cls;
  580. GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
  581. env =
  582. GNUNET_MQ_msg_extra (sdm, slen, GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT);
  583. sdm->name_len = htons (slen);
  584. sdm->reserved = htons (0);
  585. sdm->private_key = *ego->pk;
  586. GNUNET_memcpy (&sdm[1], service_name, slen);
  587. GNUNET_MQ_send (h->mq, env);
  588. return op;
  589. }
  590. /**
  591. * Create a new identity with the given name.
  592. *
  593. * @param h identity service to use
  594. * @param name desired name
  595. * @param cont function to call with the result (will only be called once)
  596. * @param cont_cls closure for @a cont
  597. * @return handle to abort the operation
  598. */
  599. struct GNUNET_IDENTITY_Operation *
  600. GNUNET_IDENTITY_create (struct GNUNET_IDENTITY_Handle *h,
  601. const char *name,
  602. GNUNET_IDENTITY_CreateContinuation cont,
  603. void *cont_cls)
  604. {
  605. struct GNUNET_IDENTITY_Operation *op;
  606. struct GNUNET_MQ_Envelope *env;
  607. struct CreateRequestMessage *crm;
  608. struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
  609. size_t slen;
  610. if (NULL == h->mq)
  611. return NULL;
  612. slen = strlen (name) + 1;
  613. if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct CreateRequestMessage))
  614. {
  615. GNUNET_break (0);
  616. return NULL;
  617. }
  618. op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
  619. op->h = h;
  620. op->create_cont = cont;
  621. op->cls = cont_cls;
  622. GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
  623. env = GNUNET_MQ_msg_extra (crm, slen, GNUNET_MESSAGE_TYPE_IDENTITY_CREATE);
  624. crm->name_len = htons (slen);
  625. crm->reserved = htons (0);
  626. pk = GNUNET_CRYPTO_ecdsa_key_create ();
  627. crm->private_key = *pk;
  628. op->pk = pk;
  629. GNUNET_memcpy (&crm[1], name, slen);
  630. GNUNET_MQ_send (h->mq, env);
  631. return op;
  632. }
  633. /**
  634. * Renames an existing identity.
  635. *
  636. * @param h identity service to use
  637. * @param old_name old name
  638. * @param new_name desired new name
  639. * @param cb function to call with the result (will only be called once)
  640. * @param cb_cls closure for @a cb
  641. * @return handle to abort the operation
  642. */
  643. struct GNUNET_IDENTITY_Operation *
  644. GNUNET_IDENTITY_rename (struct GNUNET_IDENTITY_Handle *h,
  645. const char *old_name,
  646. const char *new_name,
  647. GNUNET_IDENTITY_Continuation cb,
  648. void *cb_cls)
  649. {
  650. struct GNUNET_IDENTITY_Operation *op;
  651. struct GNUNET_MQ_Envelope *env;
  652. struct RenameMessage *grm;
  653. size_t slen_old;
  654. size_t slen_new;
  655. char *dst;
  656. if (NULL == h->mq)
  657. return NULL;
  658. slen_old = strlen (old_name) + 1;
  659. slen_new = strlen (new_name) + 1;
  660. if ((slen_old >= GNUNET_MAX_MESSAGE_SIZE) ||
  661. (slen_new >= GNUNET_MAX_MESSAGE_SIZE) ||
  662. (slen_old + slen_new >=
  663. GNUNET_MAX_MESSAGE_SIZE - sizeof (struct RenameMessage)))
  664. {
  665. GNUNET_break (0);
  666. return NULL;
  667. }
  668. op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
  669. op->h = h;
  670. op->cont = cb;
  671. op->cls = cb_cls;
  672. GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
  673. env = GNUNET_MQ_msg_extra (grm,
  674. slen_old + slen_new,
  675. GNUNET_MESSAGE_TYPE_IDENTITY_RENAME);
  676. grm->old_name_len = htons (slen_old);
  677. grm->new_name_len = htons (slen_new);
  678. dst = (char *) &grm[1];
  679. GNUNET_memcpy (dst, old_name, slen_old);
  680. GNUNET_memcpy (&dst[slen_old], new_name, slen_new);
  681. GNUNET_MQ_send (h->mq, env);
  682. return op;
  683. }
  684. /**
  685. * Delete an existing identity.
  686. *
  687. * @param h identity service to use
  688. * @param name name of the identity to delete
  689. * @param cb function to call with the result (will only be called once)
  690. * @param cb_cls closure for @a cb
  691. * @return handle to abort the operation
  692. */
  693. struct GNUNET_IDENTITY_Operation *
  694. GNUNET_IDENTITY_delete (struct GNUNET_IDENTITY_Handle *h,
  695. const char *name,
  696. GNUNET_IDENTITY_Continuation cb,
  697. void *cb_cls)
  698. {
  699. struct GNUNET_IDENTITY_Operation *op;
  700. struct GNUNET_MQ_Envelope *env;
  701. struct DeleteMessage *gdm;
  702. size_t slen;
  703. if (NULL == h->mq)
  704. return NULL;
  705. slen = strlen (name) + 1;
  706. if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct DeleteMessage))
  707. {
  708. GNUNET_break (0);
  709. return NULL;
  710. }
  711. op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
  712. op->h = h;
  713. op->cont = cb;
  714. op->cls = cb_cls;
  715. GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
  716. env = GNUNET_MQ_msg_extra (gdm, slen, GNUNET_MESSAGE_TYPE_IDENTITY_DELETE);
  717. gdm->name_len = htons (slen);
  718. gdm->reserved = htons (0);
  719. GNUNET_memcpy (&gdm[1], name, slen);
  720. GNUNET_MQ_send (h->mq, env);
  721. return op;
  722. }
  723. /**
  724. * Cancel an identity operation. Note that the operation MAY still
  725. * be executed; this merely cancels the continuation; if the request
  726. * was already transmitted, the service may still choose to complete
  727. * the operation.
  728. *
  729. * @param op operation to cancel
  730. */
  731. void
  732. GNUNET_IDENTITY_cancel (struct GNUNET_IDENTITY_Operation *op)
  733. {
  734. op->cont = NULL;
  735. op->cb = NULL;
  736. op->create_cont = NULL;
  737. if (NULL != op->pk)
  738. {
  739. GNUNET_free (op->pk);
  740. op->pk = NULL;
  741. }
  742. }
  743. /**
  744. * Disconnect from identity service
  745. *
  746. * @param h handle to destroy
  747. */
  748. void
  749. GNUNET_IDENTITY_disconnect (struct GNUNET_IDENTITY_Handle *h)
  750. {
  751. struct GNUNET_IDENTITY_Operation *op;
  752. GNUNET_assert (NULL != h);
  753. if (h->reconnect_task != NULL)
  754. {
  755. GNUNET_SCHEDULER_cancel (h->reconnect_task);
  756. h->reconnect_task = NULL;
  757. }
  758. if (NULL != h->egos)
  759. {
  760. GNUNET_CONTAINER_multihashmap_iterate (h->egos, &free_ego, h);
  761. GNUNET_CONTAINER_multihashmap_destroy (h->egos);
  762. h->egos = NULL;
  763. }
  764. while (NULL != (op = h->op_head))
  765. {
  766. GNUNET_break (NULL == op->cont);
  767. GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
  768. GNUNET_free_non_null (op->pk);
  769. GNUNET_free (op);
  770. }
  771. if (NULL != h->mq)
  772. {
  773. GNUNET_MQ_destroy (h->mq);
  774. h->mq = NULL;
  775. }
  776. GNUNET_free (h);
  777. }
  778. /* end of identity_api.c */