gnunet-abd.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070
  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-abd.c
  18. * @brief command line tool to access command line Credential service
  19. * @author Martin Schanzenbach
  20. */
  21. #include "platform.h"
  22. #include <gnunet_util_lib.h>
  23. #include <gnunet_abd_service.h>
  24. #include <gnunet_gnsrecord_lib.h>
  25. #include <gnunet_namestore_service.h>
  26. #include "delegate_misc.h"
  27. #include "abd_serialization.h"
  28. /**
  29. * Configuration we are using.
  30. */
  31. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  32. /**
  33. * Handle to the namestore.
  34. */
  35. static struct GNUNET_NAMESTORE_Handle *ns;
  36. /**
  37. * Private key for the our zone.
  38. */
  39. static struct GNUNET_CRYPTO_EcdsaPrivateKey zone_pkey;
  40. /**
  41. * EgoLookup
  42. */
  43. static struct GNUNET_IDENTITY_EgoLookup *el;
  44. /**
  45. * Handle to Credential service.
  46. */
  47. static struct GNUNET_ABD_Handle *abd;
  48. /**
  49. * Desired timeout for the lookup (default is no timeout).
  50. */
  51. static struct GNUNET_TIME_Relative timeout;
  52. /**
  53. * Handle to verify request
  54. */
  55. static struct GNUNET_ABD_Request *verify_request;
  56. /**
  57. * Handle to collect request
  58. */
  59. static struct GNUNET_ABD_Request *collect_request;
  60. /**
  61. * Task scheduled to handle timeout.
  62. */
  63. static struct GNUNET_SCHEDULER_Task *tt;
  64. /**
  65. * Return value of the commandline.
  66. */
  67. static int ret = 0;
  68. /**
  69. * Subject pubkey string
  70. */
  71. static char *subject;
  72. /**
  73. * Subject delegate string
  74. */
  75. static char *subject_delegate;
  76. /**
  77. * Credential TTL
  78. */
  79. static char *expiration;
  80. /**
  81. * Subject key
  82. */
  83. struct GNUNET_CRYPTO_EcdsaPublicKey subject_pkey;
  84. /**
  85. * Issuer key
  86. */
  87. struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey;
  88. /**
  89. * Issuer pubkey string
  90. */
  91. static char *issuer_key;
  92. /**
  93. * ego
  94. */
  95. static char *ego_name;
  96. /**
  97. * Issuer attribute
  98. */
  99. static char *issuer_attr;
  100. /**
  101. * Verify mode
  102. */
  103. static int verify;
  104. /**
  105. * Collect mode
  106. */
  107. static int collect;
  108. /**
  109. * Create mode
  110. */
  111. static int create_is;
  112. /**
  113. * Create mode
  114. */
  115. static int create_ss;
  116. /**
  117. * Create mode
  118. */
  119. static int sign_ss;
  120. /**
  121. * Signed issue credentials
  122. */
  123. static char *import;
  124. /**
  125. * Is record private
  126. */
  127. static int is_private;
  128. /**
  129. * Search direction: forward
  130. */
  131. static int forward;
  132. /**
  133. * Search direction: backward
  134. */
  135. static int backward;
  136. /**
  137. * API enum, filled and passed for collect/verify
  138. */
  139. enum GNUNET_ABD_AlgoDirectionFlags direction = 0;
  140. /**
  141. * Queue entry for the 'add' operation.
  142. */
  143. static struct GNUNET_NAMESTORE_QueueEntry *add_qe;
  144. /**
  145. * Value in binary format.
  146. */
  147. static void *data;
  148. /**
  149. * Number of bytes in #data.
  150. */
  151. static size_t data_size;
  152. /**
  153. * Type string converted to DNS type value.
  154. */
  155. static uint32_t type;
  156. /**
  157. * Type of the record to add/remove, NULL to remove all.
  158. */
  159. static char *typestring;
  160. /**
  161. * Expiration string converted to numeric value.
  162. */
  163. static uint64_t etime;
  164. /**
  165. * Is expiration time relative or absolute time?
  166. */
  167. static int etime_is_rel = GNUNET_SYSERR;
  168. /**
  169. * Fixed size of the public/private keys
  170. */
  171. static const int key_length = 52;
  172. /**
  173. * Record label for storing delegations
  174. */
  175. static char *record_label;
  176. /**
  177. * Task run on shutdown. Cleans up everything.
  178. *
  179. * @param cls unused
  180. */
  181. static void
  182. do_shutdown (void *cls)
  183. {
  184. if (NULL != verify_request)
  185. {
  186. GNUNET_ABD_request_cancel (verify_request);
  187. verify_request = NULL;
  188. }
  189. if (NULL != abd)
  190. {
  191. GNUNET_ABD_disconnect (abd);
  192. abd = NULL;
  193. }
  194. if (NULL != tt)
  195. {
  196. GNUNET_SCHEDULER_cancel (tt);
  197. tt = NULL;
  198. }
  199. if (NULL != el)
  200. {
  201. GNUNET_IDENTITY_ego_lookup_cancel (el);
  202. el = NULL;
  203. }
  204. if (NULL != add_qe)
  205. {
  206. GNUNET_NAMESTORE_cancel (add_qe);
  207. add_qe = NULL;
  208. }
  209. if (NULL != ns)
  210. {
  211. GNUNET_NAMESTORE_disconnect (ns);
  212. ns = NULL;
  213. }
  214. }
  215. /**
  216. * Task run on timeout. Triggers shutdown.
  217. *
  218. * @param cls unused
  219. */
  220. static void
  221. do_timeout (void *cls)
  222. {
  223. tt = NULL;
  224. GNUNET_SCHEDULER_shutdown ();
  225. }
  226. static void
  227. handle_intermediate_result(void *cls,
  228. struct GNUNET_ABD_Delegation *dd,
  229. bool is_bw)
  230. {
  231. char *prefix = "";
  232. if(is_bw)
  233. prefix = "Backward -";
  234. else
  235. prefix = "Forward -";
  236. printf ("%s Intermediate result: %s.%s <- %s.%s\n",
  237. prefix,
  238. GNUNET_CRYPTO_ecdsa_public_key_to_string (&dd->issuer_key),
  239. dd->issuer_attribute,
  240. GNUNET_CRYPTO_ecdsa_public_key_to_string (&dd->subject_key),
  241. dd->subject_attribute);
  242. }
  243. static void
  244. handle_collect_result (void *cls,
  245. unsigned int d_count,
  246. struct GNUNET_ABD_Delegation *dc,
  247. unsigned int c_count,
  248. struct GNUNET_ABD_Delegate *dele)
  249. {
  250. int i;
  251. char *line;
  252. verify_request = NULL;
  253. if (NULL != dele)
  254. {
  255. for (i = 0; i < c_count; i++)
  256. {
  257. line = GNUNET_ABD_delegate_to_string (&dele[i]);
  258. printf ("%s\n", line);
  259. GNUNET_free (line);
  260. }
  261. }
  262. else
  263. {
  264. printf ("Received NULL\n");
  265. }
  266. GNUNET_SCHEDULER_shutdown ();
  267. }
  268. static void
  269. handle_verify_result (void *cls,
  270. unsigned int d_count,
  271. struct GNUNET_ABD_Delegation *dc,
  272. unsigned int c_count,
  273. struct GNUNET_ABD_Delegate *dele)
  274. {
  275. int i;
  276. char *iss_key;
  277. char *sub_key;
  278. verify_request = NULL;
  279. if (NULL == dele)
  280. ret = 1;
  281. else
  282. {
  283. printf ("Delegation Chain:\n");
  284. for (i = 0; i < d_count; i++)
  285. {
  286. iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].issuer_key);
  287. sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].subject_key);
  288. if (0 != dc[i].subject_attribute_len)
  289. {
  290. printf ("(%d) %s.%s <- %s.%s\n",
  291. i,
  292. iss_key,
  293. dc[i].issuer_attribute,
  294. sub_key,
  295. dc[i].subject_attribute);
  296. }
  297. else
  298. {
  299. printf ("(%d) %s.%s <- %s\n",
  300. i,
  301. iss_key,
  302. dc[i].issuer_attribute,
  303. sub_key);
  304. }
  305. GNUNET_free (iss_key);
  306. GNUNET_free (sub_key);
  307. }
  308. printf ("\nDelegate(s):\n");
  309. for (i = 0; i < c_count; i++)
  310. {
  311. iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dele[i].issuer_key);
  312. sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dele[i].subject_key);
  313. printf ("%s.%s <- %s\n", iss_key, dele[i].issuer_attribute, sub_key);
  314. GNUNET_free (iss_key);
  315. GNUNET_free (sub_key);
  316. }
  317. printf ("Successful.\n");
  318. }
  319. GNUNET_SCHEDULER_shutdown ();
  320. }
  321. /**
  322. * Callback invoked from identity service with ego information.
  323. * An @a ego of NULL means the ego was not found.
  324. *
  325. * @param cls closure with the configuration
  326. * @param ego an ego known to identity service, or NULL
  327. */
  328. static void
  329. identity_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego)
  330. {
  331. const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
  332. el = NULL;
  333. if (NULL == ego)
  334. {
  335. if (NULL != ego_name)
  336. {
  337. fprintf (stderr,
  338. _ ("Ego `%s' not known to identity service\n"),
  339. ego_name);
  340. }
  341. GNUNET_SCHEDULER_shutdown ();
  342. return;
  343. }
  344. if (GNUNET_YES == collect)
  345. {
  346. if (GNUNET_OK !=
  347. GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
  348. strlen (issuer_key),
  349. &issuer_pkey))
  350. {
  351. fprintf (stderr,
  352. _ ("Issuer public key `%s' is not well-formed\n"),
  353. issuer_key);
  354. GNUNET_SCHEDULER_shutdown ();
  355. }
  356. privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
  357. collect_request = GNUNET_ABD_collect (abd,
  358. &issuer_pkey,
  359. issuer_attr,
  360. privkey,
  361. direction,
  362. &handle_collect_result,
  363. NULL,
  364. &handle_intermediate_result,
  365. NULL);
  366. return;
  367. }
  368. GNUNET_SCHEDULER_shutdown ();
  369. }
  370. /**
  371. * Parse expiration time.
  372. *
  373. * @param expirationstring text to parse
  374. * @param etime_is_rel[out] set to #GNUNET_YES if time is relative
  375. * @param etime[out] set to expiration time (abs or rel)
  376. * @return #GNUNET_OK on success
  377. */
  378. static int
  379. parse_expiration (const char *expirationstring,
  380. int *etime_is_rel,
  381. uint64_t *etime)
  382. {
  383. // copied from namestore/gnunet-namestore.c
  384. struct GNUNET_TIME_Relative etime_rel;
  385. struct GNUNET_TIME_Absolute etime_abs;
  386. if (0 == strcmp (expirationstring, "never"))
  387. {
  388. *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
  389. *etime_is_rel = GNUNET_NO;
  390. return GNUNET_OK;
  391. }
  392. if (GNUNET_OK ==
  393. GNUNET_STRINGS_fancy_time_to_relative (expirationstring, &etime_rel))
  394. {
  395. *etime_is_rel = GNUNET_YES;
  396. *etime = etime_rel.rel_value_us;
  397. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  398. "Storing record with relative expiration time of %s\n",
  399. GNUNET_STRINGS_relative_time_to_string (etime_rel, GNUNET_NO));
  400. return GNUNET_OK;
  401. }
  402. if (GNUNET_OK ==
  403. GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, &etime_abs))
  404. {
  405. *etime_is_rel = GNUNET_NO;
  406. *etime = etime_abs.abs_value_us;
  407. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  408. "Storing record with absolute expiration time of %s\n",
  409. GNUNET_STRINGS_absolute_time_to_string (etime_abs));
  410. return GNUNET_OK;
  411. }
  412. return GNUNET_SYSERR;
  413. }
  414. /**
  415. * Function called if lookup fails.
  416. */
  417. static void
  418. error_cb (void *cls)
  419. {
  420. fprintf (stderr, "Error occured during lookup, shutting down.\n");
  421. GNUNET_SCHEDULER_shutdown ();
  422. return;
  423. }
  424. static void
  425. add_continuation (void *cls, int32_t success, const char *emsg)
  426. {
  427. struct GNUNET_NAMESTORE_QueueEntry **qe = cls;
  428. *qe = NULL;
  429. if(GNUNET_OK == success)
  430. printf ("Adding successful.\n");
  431. else
  432. fprintf (stderr, "Error occured during adding, shutting down.\n");
  433. GNUNET_SCHEDULER_shutdown ();
  434. }
  435. static void
  436. get_existing_record (void *cls,
  437. const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
  438. const char *rec_name,
  439. unsigned int rd_count,
  440. const struct GNUNET_GNSRECORD_Data *rd)
  441. {
  442. struct GNUNET_GNSRECORD_Data rdn[rd_count + 1];
  443. struct GNUNET_GNSRECORD_Data *rde;
  444. memset (rdn, 0, sizeof (struct GNUNET_GNSRECORD_Data));
  445. GNUNET_memcpy (&rdn[1], rd, rd_count * sizeof (struct GNUNET_GNSRECORD_Data));
  446. rde = &rdn[0];
  447. rde->data = data;
  448. rde->data_size = data_size;
  449. rde->record_type = type;
  450. // Set flags
  451. if (GNUNET_YES == is_private)
  452. rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE;
  453. rde->expiration_time = etime;
  454. if (GNUNET_YES == etime_is_rel)
  455. rde->flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
  456. else if (GNUNET_NO != etime_is_rel)
  457. rde->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
  458. GNUNET_assert (NULL != rec_name);
  459. add_qe = GNUNET_NAMESTORE_records_store (ns,
  460. &zone_pkey,
  461. rec_name,
  462. rd_count + 1,
  463. rde,
  464. &add_continuation,
  465. &add_qe);
  466. return;
  467. }
  468. static void
  469. store_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego)
  470. {
  471. const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
  472. el = NULL;
  473. ns = GNUNET_NAMESTORE_connect (cfg);
  474. if (NULL == ns)
  475. {
  476. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  477. _ ("Failed to connect to namestore\n"));
  478. GNUNET_SCHEDULER_shutdown ();
  479. return;
  480. }
  481. // Key handling
  482. zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego);
  483. if (GNUNET_GNSRECORD_TYPE_DELEGATE == type)
  484. {
  485. // Parse import
  486. struct GNUNET_ABD_Delegate *cred;
  487. cred = GNUNET_ABD_delegate_from_string (import);
  488. // Get import subject public key string
  489. char *subject_pubkey_str =
  490. GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
  491. // Get zone public key string
  492. struct GNUNET_CRYPTO_EcdsaPublicKey zone_pubkey;
  493. GNUNET_IDENTITY_ego_get_public_key (ego, &zone_pubkey);
  494. char *zone_pubkey_str =
  495. GNUNET_CRYPTO_ecdsa_public_key_to_string (&zone_pubkey);
  496. // Check if the subject key in the signed import matches the zone's key it is issued to
  497. if (strcmp (zone_pubkey_str, subject_pubkey_str) != 0)
  498. {
  499. fprintf (stderr,
  500. "Import signed delegate does not match this ego's public key.\n");
  501. GNUNET_SCHEDULER_shutdown ();
  502. return;
  503. }
  504. // Expiration
  505. etime = cred->expiration.abs_value_us;
  506. etime_is_rel = GNUNET_NO;
  507. // Prepare the data to be store in the record
  508. data_size = GNUNET_ABD_delegate_serialize (cred, (char **) &data);
  509. GNUNET_free (cred);
  510. }
  511. else
  512. {
  513. // For all other types e.g. GNUNET_GNSRECORD_TYPE_ATTRIBUTE
  514. if (GNUNET_OK !=
  515. GNUNET_GNSRECORD_string_to_value (type, subject, &data, &data_size))
  516. {
  517. fprintf (stderr,
  518. "Value `%s' invalid for record type `%s'\n",
  519. subject,
  520. typestring);
  521. GNUNET_SCHEDULER_shutdown ();
  522. return;
  523. }
  524. // Take care of expiration
  525. if (NULL == expiration)
  526. {
  527. fprintf (stderr, "Missing option -e for operation 'create'\n");
  528. GNUNET_SCHEDULER_shutdown ();
  529. return;
  530. }
  531. if (GNUNET_OK != parse_expiration (expiration, &etime_is_rel, &etime))
  532. {
  533. fprintf (stderr, "Invalid time format `%s'\n", expiration);
  534. GNUNET_SCHEDULER_shutdown ();
  535. return;
  536. }
  537. }
  538. // Start lookup
  539. add_qe = GNUNET_NAMESTORE_records_lookup (ns,
  540. &zone_pkey,
  541. record_label,
  542. &error_cb,
  543. NULL,
  544. &get_existing_record,
  545. NULL);
  546. return;
  547. }
  548. static void
  549. sign_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego)
  550. {
  551. const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
  552. struct GNUNET_ABD_Delegate *dele;
  553. struct GNUNET_TIME_Absolute etime_abs;
  554. char *res;
  555. el = NULL;
  556. // work on expiration time
  557. if (NULL == expiration)
  558. {
  559. fprintf (stderr, "Please specify a TTL\n");
  560. GNUNET_SCHEDULER_shutdown ();
  561. return;
  562. }
  563. else if (GNUNET_OK !=
  564. GNUNET_STRINGS_fancy_time_to_absolute (expiration, &etime_abs))
  565. {
  566. fprintf (stderr,
  567. "%s is not a valid ttl! Only absolute times are accepted!\n",
  568. expiration);
  569. GNUNET_SCHEDULER_shutdown ();
  570. return;
  571. }
  572. // If contains a space - split it by the first space only - assume first entry is subject followed by attribute(s)
  573. char *subject_pubkey_str;
  574. char *subject_attr = NULL;
  575. char *token;
  576. // Subject Public Key
  577. token = strtok (subject, " ");
  578. if (key_length == strlen (token))
  579. {
  580. subject_pubkey_str = token;
  581. }
  582. else
  583. {
  584. fprintf (stderr, "Key error, wrong length: %ld!\n", strlen (token));
  585. GNUNET_SCHEDULER_shutdown ();
  586. return;
  587. }
  588. // Subject Attribute(s)
  589. token = strtok (NULL, " ");
  590. if (NULL != token)
  591. {
  592. subject_attr = token;
  593. }
  594. // work on keys
  595. privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
  596. if (GNUNET_OK !=
  597. GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pubkey_str,
  598. strlen (subject_pubkey_str),
  599. &subject_pkey))
  600. {
  601. fprintf (stderr,
  602. "Subject public key `%s' is not well-formed\n",
  603. subject_pubkey_str);
  604. GNUNET_SCHEDULER_shutdown ();
  605. return;
  606. }
  607. // Sign delegate
  608. dele = GNUNET_ABD_delegate_issue (privkey,
  609. &subject_pkey,
  610. issuer_attr,
  611. subject_attr,
  612. &etime_abs);
  613. res = GNUNET_ABD_delegate_to_string (dele);
  614. GNUNET_free (dele);
  615. printf ("%s\n", res);
  616. GNUNET_free_non_null (ego_name);
  617. ego_name = NULL;
  618. GNUNET_SCHEDULER_shutdown ();
  619. }
  620. /**
  621. * Main function that will be run.
  622. *
  623. * @param cls closure
  624. * @param args remaining command-line arguments
  625. * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  626. * @param c configuration
  627. */
  628. static void
  629. run (void *cls,
  630. char *const *args,
  631. const char *cfgfile,
  632. const struct GNUNET_CONFIGURATION_Handle *c)
  633. {
  634. cfg = c;
  635. tt = GNUNET_SCHEDULER_add_delayed (timeout, &do_timeout, NULL);
  636. GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
  637. // Check relevant cmdline parameters
  638. if (GNUNET_YES == create_is)
  639. {
  640. if (NULL == ego_name)
  641. {
  642. fprintf (stderr, "Missing option '-ego'\n");
  643. GNUNET_SCHEDULER_shutdown ();
  644. return;
  645. }
  646. if (NULL == issuer_attr)
  647. {
  648. fprintf (stderr, "Missing option '-attribute' for issuer attribute\n");
  649. GNUNET_SCHEDULER_shutdown ();
  650. return;
  651. }
  652. if (NULL == subject)
  653. {
  654. fprintf (stderr, "Missing option -subject for operation 'create'.'\n");
  655. GNUNET_SCHEDULER_shutdown ();
  656. return;
  657. }
  658. // Lookup ego, on success call store_cb and store as ATTRIBUTE type
  659. type = GNUNET_GNSRECORD_TYPE_ATTRIBUTE;
  660. record_label = issuer_attr;
  661. el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &store_cb, (void *) cfg);
  662. return;
  663. }
  664. if (GNUNET_YES == create_ss)
  665. {
  666. // check if signed parameter has been passed in cmd line call
  667. if (NULL == import)
  668. {
  669. fprintf (stderr, "'import' required\n");
  670. GNUNET_SCHEDULER_shutdown ();
  671. return;
  672. }
  673. type = GNUNET_GNSRECORD_TYPE_DELEGATE;
  674. record_label = GNUNET_GNS_EMPTY_LABEL_AT;
  675. // Store subject side
  676. el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &store_cb, (void *) cfg);
  677. return;
  678. }
  679. if (GNUNET_YES == sign_ss)
  680. {
  681. if (NULL == ego_name)
  682. {
  683. fprintf (stderr, "ego required\n");
  684. GNUNET_SCHEDULER_shutdown ();
  685. return;
  686. }
  687. if (NULL == subject)
  688. {
  689. fprintf (stderr, "Subject public key needed\n");
  690. GNUNET_SCHEDULER_shutdown ();
  691. return;
  692. }
  693. // lookup ego and call function sign_cb on success
  694. el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &sign_cb, (void *) cfg);
  695. return;
  696. }
  697. if (GNUNET_NO == forward && GNUNET_NO == backward)
  698. {
  699. // set default: bidirectional
  700. forward = GNUNET_YES;
  701. backward = GNUNET_YES;
  702. }
  703. if (GNUNET_YES == forward)
  704. direction |= GNUNET_ABD_FLAG_FORWARD;
  705. if (GNUNET_YES == backward)
  706. direction |= GNUNET_ABD_FLAG_BACKWARD;
  707. if (GNUNET_YES == collect)
  708. {
  709. if (NULL == issuer_key)
  710. {
  711. fprintf (stderr, _ ("Issuer public key not well-formed\n"));
  712. GNUNET_SCHEDULER_shutdown ();
  713. return;
  714. }
  715. abd = GNUNET_ABD_connect (cfg);
  716. if (NULL == abd)
  717. {
  718. fprintf (stderr, _ ("Failed to connect to ABD\n"));
  719. GNUNET_SCHEDULER_shutdown ();
  720. return;
  721. }
  722. if (NULL == issuer_attr)
  723. {
  724. fprintf (stderr, _ ("You must provide issuer the attribute\n"));
  725. GNUNET_SCHEDULER_shutdown ();
  726. return;
  727. }
  728. if (NULL == ego_name)
  729. {
  730. fprintf (stderr, _ ("ego required\n"));
  731. GNUNET_SCHEDULER_shutdown ();
  732. return;
  733. }
  734. el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &identity_cb, (void *) cfg);
  735. return;
  736. }
  737. if (NULL == subject)
  738. {
  739. fprintf (stderr, _ ("Subject public key needed\n"));
  740. GNUNET_SCHEDULER_shutdown ();
  741. return;
  742. }
  743. if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (subject,
  744. strlen (subject),
  745. &subject_pkey))
  746. {
  747. fprintf (stderr,
  748. _ ("Subject public key `%s' is not well-formed\n"),
  749. subject);
  750. GNUNET_SCHEDULER_shutdown ();
  751. return;
  752. }
  753. if (GNUNET_YES == verify)
  754. {
  755. if (NULL == issuer_key)
  756. {
  757. fprintf (stderr, _ ("Issuer public key not well-formed\n"));
  758. GNUNET_SCHEDULER_shutdown ();
  759. return;
  760. }
  761. if (GNUNET_OK !=
  762. GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
  763. strlen (issuer_key),
  764. &issuer_pkey))
  765. {
  766. fprintf (stderr,
  767. _ ("Issuer public key `%s' is not well-formed\n"),
  768. issuer_key);
  769. GNUNET_SCHEDULER_shutdown ();
  770. return;
  771. }
  772. abd = GNUNET_ABD_connect (cfg);
  773. if (NULL == abd)
  774. {
  775. fprintf (stderr, _ ("Failed to connect to ABD\n"));
  776. GNUNET_SCHEDULER_shutdown ();
  777. return;
  778. }
  779. if (NULL == issuer_attr || NULL == subject_delegate)
  780. {
  781. fprintf (stderr, _ ("You must provide issuer and subject attributes\n"));
  782. GNUNET_SCHEDULER_shutdown ();
  783. return;
  784. }
  785. //Subject credentials are comma separated
  786. char *tmp = GNUNET_strdup (subject_delegate);
  787. char *tok = strtok (tmp, ",");
  788. if (NULL == tok)
  789. {
  790. fprintf (stderr, "Invalid subject credentials\n");
  791. GNUNET_free (tmp);
  792. GNUNET_SCHEDULER_shutdown ();
  793. return;
  794. }
  795. int count = 1;
  796. int i;
  797. while (NULL != (tok = strtok (NULL, ",")))
  798. count++;
  799. struct GNUNET_ABD_Delegate delegates[count];
  800. struct GNUNET_ABD_Delegate *dele;
  801. GNUNET_free (tmp);
  802. tmp = GNUNET_strdup (subject_delegate);
  803. tok = strtok (tmp, ",");
  804. for (i = 0; i < count; i++)
  805. {
  806. dele = GNUNET_ABD_delegate_from_string (tok);
  807. GNUNET_memcpy (&delegates[i],
  808. dele,
  809. sizeof (struct GNUNET_ABD_Delegate));
  810. delegates[i].issuer_attribute = GNUNET_strdup (dele->issuer_attribute);
  811. tok = strtok (NULL, ",");
  812. GNUNET_free (dele);
  813. }
  814. verify_request = GNUNET_ABD_verify (abd,
  815. &issuer_pkey,
  816. issuer_attr,
  817. &subject_pkey,
  818. count,
  819. delegates,
  820. direction,
  821. &handle_verify_result,
  822. NULL,
  823. &handle_intermediate_result,
  824. NULL);
  825. for (i = 0; i < count; i++)
  826. {
  827. GNUNET_free ((char *) delegates[i].issuer_attribute);
  828. }
  829. GNUNET_free (tmp);
  830. }
  831. else
  832. {
  833. fprintf (stderr,
  834. _ (
  835. "Please specify name to lookup, subject key and issuer key!\n"));
  836. GNUNET_SCHEDULER_shutdown ();
  837. }
  838. return;
  839. }
  840. /**
  841. * The main function for gnunet-gns.
  842. *
  843. * @param argc number of arguments from the command line
  844. * @param argv command line arguments
  845. * @return 0 ok, 1 on error
  846. */
  847. int
  848. main (int argc, char *const *argv)
  849. {
  850. struct GNUNET_GETOPT_CommandLineOption options[] =
  851. {GNUNET_GETOPT_option_flag ('V',
  852. "verify",
  853. gettext_noop (
  854. "verify credential against attribute"),
  855. &verify),
  856. GNUNET_GETOPT_option_string (
  857. 's',
  858. "subject",
  859. "PKEY",
  860. gettext_noop (
  861. "The public key of the subject to lookup the"
  862. "credential for, or for issuer side storage: subject and its attributes"),
  863. &subject),
  864. GNUNET_GETOPT_option_string (
  865. 'd',
  866. "delegate",
  867. "DELE",
  868. gettext_noop ("The private, signed delegate presented by the subject"),
  869. &subject_delegate),
  870. GNUNET_GETOPT_option_string (
  871. 'i',
  872. "issuer",
  873. "PKEY",
  874. gettext_noop (
  875. "The public key of the authority to verify the credential against"),
  876. &issuer_key),
  877. GNUNET_GETOPT_option_string ('e',
  878. "ego",
  879. "EGO",
  880. gettext_noop ("The ego/zone name to use"),
  881. &ego_name),
  882. GNUNET_GETOPT_option_string (
  883. 'a',
  884. "attribute",
  885. "ATTR",
  886. gettext_noop ("The issuer attribute to verify against or to issue"),
  887. &issuer_attr),
  888. GNUNET_GETOPT_option_string ('T',
  889. "ttl",
  890. "EXP",
  891. gettext_noop (
  892. "The time to live for the credential."
  893. "e.g. 5m, 6h, \"1990-12-30 12:00:00\""),
  894. &expiration),
  895. GNUNET_GETOPT_option_flag ('g',
  896. "collect",
  897. gettext_noop ("collect credentials"),
  898. &collect),
  899. GNUNET_GETOPT_option_flag ('U',
  900. "createIssuerSide",
  901. gettext_noop (
  902. "Create and issue a credential issuer side."),
  903. &create_is),
  904. GNUNET_GETOPT_option_flag ('C',
  905. "createSubjectSide",
  906. gettext_noop (
  907. "Issue a credential subject side."),
  908. &create_ss),
  909. GNUNET_GETOPT_option_flag (
  910. 'S',
  911. "signSubjectSide",
  912. gettext_noop ("Create, sign and return a credential subject side."),
  913. &sign_ss),
  914. GNUNET_GETOPT_option_string (
  915. 'x',
  916. "import",
  917. "IMP",
  918. gettext_noop (
  919. "Import signed credentials that should be issued to a zone/ego"),
  920. &import),
  921. GNUNET_GETOPT_option_flag ('P',
  922. "private",
  923. gettext_noop ("Create private record entry."),
  924. &is_private),
  925. GNUNET_GETOPT_option_flag (
  926. 'F',
  927. "forward",
  928. gettext_noop (
  929. "Indicates that the collect/verify process is done via forward search."),
  930. &forward),
  931. GNUNET_GETOPT_option_flag (
  932. 'B',
  933. "backward",
  934. gettext_noop (
  935. "Indicates that the collect/verify process is done via forward search."),
  936. &backward),
  937. GNUNET_GETOPT_OPTION_END};
  938. timeout = GNUNET_TIME_UNIT_FOREVER_REL;
  939. if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
  940. return 2;
  941. GNUNET_log_setup ("gnunet-abd", "WARNING", NULL);
  942. if (GNUNET_OK != GNUNET_PROGRAM_run (argc,
  943. argv,
  944. "gnunet-abd",
  945. _ ("GNUnet abd resolver tool"),
  946. options,
  947. &run,
  948. NULL))
  949. ret = 1;
  950. GNUNET_free ((void *) argv);
  951. return ret;
  952. }
  953. /* end of gnunet-abd.c */