gnunet-gns-import.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2012-2013 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 gnunet-gns.c
  18. * @brief binary version of gnunet-gns-import.sh
  19. * (for OSes that have no POSIX shell).
  20. * @author LRN
  21. */
  22. #include "platform.h"
  23. #include <gnunet_util_lib.h>
  24. #include <gnunet_gnsrecord_lib.h>
  25. #include <gnunet_identity_service.h>
  26. #include <gnunet_namestore_service.h>
  27. /**
  28. * Configuration we are using.
  29. */
  30. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  31. /**
  32. * Handle to IDENTITY service.
  33. */
  34. static struct GNUNET_IDENTITY_Handle *sh;
  35. /**
  36. * Zone iterator for master zone
  37. */
  38. struct GNUNET_NAMESTORE_ZoneIterator *list_it;
  39. /**
  40. * Handle to the namestore.
  41. */
  42. static struct GNUNET_NAMESTORE_Handle *ns;
  43. /**
  44. * String version of PKEY for master-zone.
  45. */
  46. static char *master_zone_pkey;
  47. /**
  48. * Binary version of PKEY for master-zone.
  49. */
  50. static struct GNUNET_CRYPTO_EcdsaPrivateKey master_pk;
  51. /**
  52. * String version of PKEY for private-zone.
  53. */
  54. static char *private_zone_pkey;
  55. /**
  56. * String version of PKEY for pin-zone.
  57. */
  58. static char *pin_zone_pkey =
  59. "72QC35CO20UJN1E91KPJFNT9TG4CLKAPB4VK9S3Q758S9MLBRKOG";
  60. /**
  61. * Set to GNUNET_YES if private record was found;
  62. */
  63. static int found_private_rec = GNUNET_NO;
  64. /**
  65. * Set to GNUNET_YES if pin record was found;
  66. */
  67. static int found_pin_rec = GNUNET_NO;
  68. /**
  69. * Exit code.
  70. */
  71. static int ret;
  72. static int
  73. run_process_and_wait (int pipe_control,
  74. enum GNUNET_OS_InheritStdioFlags std_inheritance,
  75. struct GNUNET_DISK_PipeHandle *pipe_stdin,
  76. struct GNUNET_DISK_PipeHandle *pipe_stdout,
  77. enum GNUNET_OS_ProcessStatusType *st,
  78. unsigned long *code,
  79. const char *filename, ...)
  80. {
  81. static struct GNUNET_OS_Process *p;
  82. int arglen;
  83. char *arg;
  84. char *args;
  85. char *argp;
  86. va_list ap, apc1, apc2;
  87. va_start (ap, filename);
  88. va_copy (apc1, ap);
  89. va_copy (apc2, ap);
  90. arglen = 0;
  91. while (NULL != (arg = va_arg (apc1, char *)))
  92. arglen += strlen (arg) + 1;
  93. va_end (apc1);
  94. args = argp = GNUNET_malloc (arglen);
  95. while (NULL != (arg = va_arg (apc2, char *)))
  96. {
  97. strcpy (argp, arg);
  98. argp += strlen (arg);
  99. *argp = ' ';
  100. argp += 1;
  101. }
  102. va_end (apc2);
  103. if (arglen > 0)
  104. argp[-1] = '\0';
  105. p = GNUNET_OS_start_process_va (pipe_control, std_inheritance,
  106. pipe_stdin,
  107. pipe_stdout,
  108. NULL,
  109. filename, ap);
  110. va_end (ap);
  111. if (NULL == p)
  112. {
  113. ret = 3;
  114. fprintf (stderr, "Failed to run `%s'\n", args);
  115. GNUNET_free (args);
  116. return 1;
  117. }
  118. if (GNUNET_OK != GNUNET_OS_process_wait (p))
  119. {
  120. ret = 4;
  121. fprintf (stderr, "Failed to wait for `%s'\n", args);
  122. GNUNET_free (args);
  123. return 1;
  124. }
  125. switch (GNUNET_OS_process_status (p, st, code))
  126. {
  127. case GNUNET_OK:
  128. break;
  129. case GNUNET_NO:
  130. ret = 5;
  131. fprintf (stderr, "`%s' is still running\n", args);
  132. GNUNET_free (args);
  133. return 1;
  134. default:
  135. case GNUNET_SYSERR:
  136. ret = 6;
  137. fprintf (stderr, "Failed to check the status of `%s'\n", args);
  138. GNUNET_free (args);
  139. return 1;
  140. }
  141. return 0;
  142. }
  143. static void
  144. check_pkey (unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd,
  145. char *pk, int *found_rec)
  146. {
  147. int i;
  148. for (i = 0; i < rd_len; i++)
  149. {
  150. char *s;
  151. if ((GNUNET_GNSRECORD_TYPE_PKEY != rd[i].record_type) ||
  152. (rd[i].data_size != sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
  153. continue;
  154. s = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
  155. rd[i].data,
  156. rd[i].data_size);
  157. if (NULL == s)
  158. continue;
  159. if (0 == strcmp (s, pk))
  160. *found_rec = GNUNET_YES;
  161. GNUNET_free (s);
  162. }
  163. }
  164. /**
  165. * Process a record that was stored in the namestore.
  166. *
  167. * @param cls closure
  168. * @param zone_key private key of the zone
  169. * @param rname name that is being mapped (at most 255 characters long)
  170. * @param rd_len number of entries in @a rd array
  171. * @param rd array of records with data to store
  172. */
  173. static void
  174. zone_iterator (void *cls,
  175. const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
  176. const char *rname, unsigned int rd_len,
  177. const struct GNUNET_GNSRECORD_Data *rd)
  178. {
  179. if (NULL != rname)
  180. {
  181. if (0 == strcmp (rname, "private"))
  182. check_pkey (rd_len, rd, private_zone_pkey, &found_private_rec);
  183. else if (0 == strcmp (rname, "pin"))
  184. check_pkey (rd_len, rd, pin_zone_pkey, &found_pin_rec);
  185. }
  186. GNUNET_NAMESTORE_zone_iterator_next (list_it);
  187. }
  188. static void
  189. zone_iteration_error (void *cls)
  190. {
  191. enum GNUNET_OS_ProcessStatusType st;
  192. unsigned long code;
  193. if (! found_private_rec)
  194. {
  195. if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  196. NULL, NULL, &st, &code,
  197. "gnunet-namestore",
  198. "gnunet-namestore", "-z", "master-zone",
  199. "-a", "-e", "never", "-n", "private", "-p",
  200. "-t", "PKEY", "-V",
  201. private_zone_pkey, NULL))
  202. {
  203. ret = 8;
  204. return;
  205. }
  206. }
  207. if (! found_pin_rec)
  208. {
  209. if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  210. NULL, NULL, &st, &code,
  211. "gnunet-namestore",
  212. "gnunet-namestore", "-z", "master-zone",
  213. "-a", "-e", "never", "-n", "pin", "-p", "-t",
  214. "PKEY", "-V", pin_zone_pkey,
  215. NULL))
  216. {
  217. ret = 10;
  218. return;
  219. }
  220. }
  221. list_it = NULL;
  222. GNUNET_SCHEDULER_shutdown ();
  223. }
  224. static void
  225. zone_iteration_finished (void *cls)
  226. {
  227. }
  228. /**
  229. * Get master-zone and private-zone keys.
  230. *
  231. * This function is initially called for all egos and then again
  232. * whenever a ego's identifier changes or if it is deleted. At the
  233. * end of the initial pass over all egos, the function is once called
  234. * with 'NULL' for 'ego'. That does NOT mean that the callback won't
  235. * be invoked in the future or that there was an error.
  236. *
  237. * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
  238. * this function is only called ONCE, and 'NULL' being passed in
  239. * 'ego' does indicate an error (i.e. name is taken or no default
  240. * value is known). If 'ego' is non-NULL and if '*ctx'
  241. * is set in those callbacks, the value WILL be passed to a subsequent
  242. * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
  243. * that one was not NULL).
  244. *
  245. * When an identity is renamed, this function is called with the
  246. * (known) ego but the NEW identifier.
  247. *
  248. * When an identity is deleted, this function is called with the
  249. * (known) ego and "NULL" for the 'identifier'. In this case,
  250. * the 'ego' is henceforth invalid (and the 'ctx' should also be
  251. * cleaned up).
  252. *
  253. * @param cls closure
  254. * @param ego ego handle
  255. * @param ctx context for application to store data for this ego
  256. * (during the lifetime of this process, initially NULL)
  257. * @param identifier identifier assigned by the user for this ego,
  258. * NULL if the user just deleted the ego and it
  259. * must thus no longer be used
  260. */
  261. static void
  262. get_ego (void *cls,
  263. struct GNUNET_IDENTITY_Ego *ego,
  264. void **ctx,
  265. const char *identifier)
  266. {
  267. static struct GNUNET_CRYPTO_EcdsaPublicKey pk;
  268. if (NULL == ego)
  269. {
  270. if ((NULL == master_zone_pkey) ||
  271. (NULL == private_zone_pkey) )
  272. {
  273. ret = 11;
  274. GNUNET_SCHEDULER_shutdown ();
  275. return;
  276. }
  277. list_it = GNUNET_NAMESTORE_zone_iteration_start (ns,
  278. &master_pk,
  279. &zone_iteration_error,
  280. NULL, &zone_iterator, NULL,
  281. &zone_iteration_finished,
  282. NULL);
  283. if (NULL == list_it)
  284. {
  285. ret = 12;
  286. GNUNET_SCHEDULER_shutdown ();
  287. }
  288. return;
  289. }
  290. GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
  291. if (NULL != identifier)
  292. {
  293. if ((NULL == master_zone_pkey) && (0 == strcmp ("master-zone",
  294. identifier)) )
  295. {
  296. master_zone_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
  297. master_pk = *GNUNET_IDENTITY_ego_get_private_key (ego);
  298. }
  299. else if ((NULL == private_zone_pkey) && (0 == strcmp ("private-zone",
  300. identifier)) )
  301. private_zone_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
  302. }
  303. }
  304. /**
  305. * Task run on shutdown.
  306. *
  307. * @param cls NULL
  308. */
  309. static void
  310. shutdown_task (void *cls)
  311. {
  312. GNUNET_free_non_null (master_zone_pkey);
  313. master_zone_pkey = NULL;
  314. GNUNET_free_non_null (private_zone_pkey);
  315. private_zone_pkey = NULL;
  316. if (NULL != list_it)
  317. {
  318. GNUNET_NAMESTORE_zone_iteration_stop (list_it);
  319. list_it = NULL;
  320. }
  321. if (NULL != ns)
  322. {
  323. GNUNET_NAMESTORE_disconnect (ns);
  324. ns = NULL;
  325. }
  326. if (NULL != sh)
  327. {
  328. GNUNET_IDENTITY_disconnect (sh);
  329. sh = NULL;
  330. }
  331. }
  332. /**
  333. * Main function that will be run.
  334. *
  335. * @param cls closure
  336. * @param args remaining command-line arguments
  337. * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  338. * @param c configuration
  339. */
  340. static void
  341. run (void *cls, char *const *args, const char *cfgfile,
  342. const struct GNUNET_CONFIGURATION_Handle *c)
  343. {
  344. enum GNUNET_OS_ProcessStatusType st;
  345. unsigned long code;
  346. cfg = c;
  347. if (0 != run_process_and_wait (GNUNET_NO, 0, NULL, NULL, &st, &code,
  348. "gnunet-arm",
  349. "gnunet-arm", "-I", NULL))
  350. {
  351. if (7 == ret)
  352. fprintf (stderr,
  353. "GNUnet is not running, please start GNUnet before running import\n");
  354. return;
  355. }
  356. if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  357. NULL, NULL, &st, &code,
  358. "gnunet-identity",
  359. "gnunet-identity", "-C", "master-zone", NULL))
  360. return;
  361. if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  362. NULL, NULL, &st, &code,
  363. "gnunet-identity",
  364. "gnunet-identity", "-C", "private-zone", NULL))
  365. return;
  366. if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  367. NULL, NULL, &st, &code,
  368. "gnunet-identity",
  369. "gnunet-identity", "-C", "sks-zone", NULL))
  370. return;
  371. if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  372. NULL, NULL, &st, &code,
  373. "gnunet-identity",
  374. "gnunet-identity", "-e", "master-zone", "-s",
  375. "gns-master", NULL))
  376. return;
  377. if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  378. NULL, NULL, &st, &code,
  379. "gnunet-identity",
  380. "gnunet-identity", "-e", "master-zone", "-s",
  381. "namestore", NULL))
  382. return;
  383. if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  384. NULL, NULL, &st, &code,
  385. "gnunet-identity",
  386. "gnunet-identity", "-e", "master-zone", "-s",
  387. "gns-proxy", NULL))
  388. return;
  389. if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  390. NULL, NULL, &st, &code,
  391. "gnunet-identity",
  392. "gnunet-identity", "-e", "master-zone", "-s",
  393. "gns-intercept", NULL))
  394. return;
  395. if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  396. NULL, NULL, &st, &code,
  397. "gnunet-identity",
  398. "gnunet-identity", "-e", "private-zone", "-s",
  399. "gns-private", NULL))
  400. return;
  401. if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  402. NULL, NULL, &st, &code,
  403. "gnunet-identity",
  404. "gnunet-identity", "-e", "sks-zone", "-s",
  405. "fs-sks", NULL))
  406. return;
  407. ns = GNUNET_NAMESTORE_connect (cfg);
  408. sh = GNUNET_IDENTITY_connect (cfg, &get_ego, NULL);
  409. GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
  410. }
  411. /**
  412. * The main function for gnunet-gns.
  413. *
  414. * @param argc number of arguments from the command line
  415. * @param argv command line arguments
  416. * @return 0 ok, 1 on error
  417. */
  418. int
  419. main (int argc, char *const *argv)
  420. {
  421. static const struct GNUNET_GETOPT_CommandLineOption options[] = {
  422. GNUNET_GETOPT_OPTION_END
  423. };
  424. int r;
  425. if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
  426. return 2;
  427. GNUNET_log_setup ("gnunet-gns-import", "WARNING", NULL);
  428. ret = 0;
  429. r = GNUNET_PROGRAM_run (argc, argv, "gnunet-gns-import",
  430. _ (
  431. "This program will import some GNS authorities into your GNS namestore."),
  432. options,
  433. &run, NULL);
  434. GNUNET_free ((void *) argv);
  435. return GNUNET_OK == r ? ret : 1;
  436. }
  437. /* end of gnunet-gns-import.c */