2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @author Martin Schanzenbach
22 * @file src/reclaim/gnunet-reclaim.c
23 * @brief Identity Provider utility
29 #include "gnunet_util_lib.h"
31 #include "gnunet_identity_service.h"
32 #include "gnunet_namestore_service.h"
33 #include "gnunet_reclaim_service.h"
34 #include "gnunet_signatures.h"
46 * List attestations flag
48 static int list_attestations;
51 * Attestation ID string
53 static char *attestation_id;
58 static struct GNUNET_RECLAIM_Identifier attestation;
63 static char *attestation_name;
68 static int attestation_exists;
78 static char *attr_name;
83 static char *attr_value;
88 static char *issue_attrs;
93 static char *consume_ticket;
98 static char *type_str;
103 static char *revoke_ticket;
108 static int list_tickets;
113 static char *ego_name;
118 static struct GNUNET_IDENTITY_Handle *identity_handle;
123 static struct GNUNET_RECLAIM_Handle *reclaim_handle;
128 static struct GNUNET_RECLAIM_Operation *reclaim_op;
133 static struct GNUNET_RECLAIM_AttributeIterator *attr_iterator;
136 * Attestation iterator
138 static struct GNUNET_RECLAIM_AttestationIterator *attest_iterator;
144 static struct GNUNET_RECLAIM_TicketIterator *ticket_iterator;
149 static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
154 static const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey;
159 static struct GNUNET_CRYPTO_EcdsaPublicKey rp_key;
164 static struct GNUNET_RECLAIM_Ticket ticket;
169 static struct GNUNET_RECLAIM_AttributeList *attr_list;
172 * Attribute expiration interval
174 static struct GNUNET_TIME_Relative exp_interval;
179 static struct GNUNET_SCHEDULER_Task *timeout;
184 static struct GNUNET_SCHEDULER_Task *cleanup_task;
189 struct GNUNET_RECLAIM_Attribute *claim;
194 static char *attr_delete;
197 * Claim object to delete
199 static struct GNUNET_RECLAIM_Attribute *attr_to_delete;
202 do_cleanup (void *cls)
206 GNUNET_SCHEDULER_cancel (timeout);
207 if (NULL != reclaim_op)
208 GNUNET_RECLAIM_cancel (reclaim_op);
209 if (NULL != attr_iterator)
210 GNUNET_RECLAIM_get_attributes_stop (attr_iterator);
211 if (NULL != attest_iterator)
212 GNUNET_RECLAIM_get_attestations_stop (attest_iterator);
213 if (NULL != ticket_iterator)
214 GNUNET_RECLAIM_ticket_iteration_stop (ticket_iterator);
215 if (NULL != reclaim_handle)
216 GNUNET_RECLAIM_disconnect (reclaim_handle);
217 if (NULL != identity_handle)
218 GNUNET_IDENTITY_disconnect (identity_handle);
220 GNUNET_free (abe_key);
221 if (NULL != attr_list)
222 GNUNET_free (attr_list);
223 if (NULL != attr_to_delete)
224 GNUNET_free (attr_to_delete);
229 ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
237 GNUNET_STRINGS_data_to_string_alloc (ticket,
239 struct GNUNET_RECLAIM_Ticket));
240 printf ("%s\n", ticket_str);
241 GNUNET_free (ticket_str);
243 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
248 store_cont (void *cls, int32_t success, const char *emsg)
251 if (GNUNET_SYSERR == success)
253 fprintf (stderr, "%s\n", emsg);
255 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
260 process_attrs (void *cls,
261 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
262 const struct GNUNET_RECLAIM_Attribute *attr,
263 const struct GNUNET_RECLAIM_Attestation *attest)
267 const char *attr_type;
269 if (NULL == identity)
272 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
280 attr_type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
281 id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
285 value_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
291 struct GNUNET_RECLAIM_AttributeListEntry *ale;
292 struct GNUNET_RECLAIM_AttributeList *al
293 = GNUNET_RECLAIM_attestation_get_attributes (attest);
295 for (ale = al->list_head; NULL != ale; ale = ale->next)
297 if (0 != strncmp (attr->data, ale->attribute->name, attr->data_size))
300 = GNUNET_RECLAIM_attribute_value_to_string (ale->attribute->type,
309 "Name: %s; Value: %s (%s); Flag %u; ID: %s %s\n",
311 (NULL != value_str) ? value_str : "???",
315 (NULL == attest) ? "" : "(ATTESTED)");
316 GNUNET_free_non_null (value_str);
322 ticket_iter_err (void *cls)
324 ticket_iterator = NULL;
325 fprintf (stderr, "Failed to iterate over tickets\n");
326 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
331 ticket_iter_fin (void *cls)
333 ticket_iterator = NULL;
334 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
339 ticket_iter (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
346 GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
348 GNUNET_CRYPTO_EcdsaPublicKey));
349 ref = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(ticket->rnd));
351 GNUNET_STRINGS_data_to_string_alloc (ticket,
352 sizeof(struct GNUNET_RECLAIM_Ticket));
353 fprintf (stdout, "Ticket: %s | ID: %s | Audience: %s\n", tkt, ref, aud);
357 GNUNET_RECLAIM_ticket_iteration_next (ticket_iterator);
362 iter_error (void *cls)
364 attr_iterator = NULL;
365 attest_iterator = NULL;
366 fprintf (stderr, "Failed\n");
368 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
373 timeout_task (void *cls)
377 fprintf (stderr, "Timeout\n");
378 if (NULL == cleanup_task)
379 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
384 process_rvk (void *cls, int success, const char *msg)
387 if (GNUNET_OK != success)
389 fprintf (stderr, "Revocation failed.\n");
392 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
397 process_delete (void *cls, int success, const char *msg)
400 if (GNUNET_OK != success)
402 fprintf (stderr, "Deletion failed.\n");
405 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
410 iter_finished (void *cls)
416 attr_iterator = NULL;
419 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
425 reclaim_op = GNUNET_RECLAIM_ticket_issue (reclaim_handle,
435 reclaim_op = GNUNET_RECLAIM_ticket_consume (reclaim_handle,
440 timeout = GNUNET_SCHEDULER_add_delayed (
441 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
448 reclaim_op = GNUNET_RECLAIM_ticket_revoke (reclaim_handle,
457 if (NULL == attr_to_delete)
459 fprintf (stdout, "No such attribute ``%s''\n", attr_delete);
462 reclaim_op = GNUNET_RECLAIM_attribute_delete (reclaim_handle,
471 if (NULL == type_str)
472 type = GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING;
474 type = GNUNET_RECLAIM_attribute_typename_to_number (type_str);
476 GNUNET_assert (GNUNET_SYSERR !=
477 GNUNET_RECLAIM_attribute_string_to_value (type,
485 claim->data_size = data_size;
490 GNUNET_RECLAIM_attribute_new (attr_name, NULL, type, data, data_size);
492 if (NULL != attestation_id)
494 claim->attestation = attestation;
496 reclaim_op = GNUNET_RECLAIM_attribute_store (reclaim_handle,
506 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
512 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
513 const struct GNUNET_RECLAIM_Attribute *attr)
515 struct GNUNET_RECLAIM_AttributeListEntry *le;
520 const char *attr_type;
522 if ((NULL != attr_name) && (NULL != claim))
524 if (0 == strcasecmp (attr_name, attr->name))
526 claim = GNUNET_RECLAIM_attribute_new (attr->name,
533 else if (issue_attrs)
535 attrs_tmp = GNUNET_strdup (issue_attrs);
536 attr_str = strtok (attrs_tmp, ",");
537 while (NULL != attr_str)
539 if (0 != strcasecmp (attr_str, attr->name))
541 attr_str = strtok (NULL, ",");
544 le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
545 le->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
550 le->attribute->flag = attr->flag;
551 le->attribute->id = attr->id;
552 GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
553 attr_list->list_tail,
557 GNUNET_free (attrs_tmp);
559 else if (attr_delete && (NULL == attr_to_delete))
561 label = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
562 if (0 == strcasecmp (attr_delete, label))
564 attr_to_delete = GNUNET_RECLAIM_attribute_new (attr->name,
569 attr_to_delete->id = attr->id;
575 attr_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
578 attr_type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
579 id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
580 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attr->attestation))
583 "%s: ``%s'' (%s); ID: %s\n",
592 GNUNET_STRINGS_data_to_string_alloc (&attr->attestation,
593 sizeof(attr->attestation));
595 "%s: <``%s'' in attestation %s> (%s); ID: %s\n",
601 GNUNET_free (attest_id);
606 GNUNET_RECLAIM_get_attributes_next (attr_iterator);
611 attest_iter_finished (void *cls)
613 attest_iterator = NULL;
615 // Add new attestation
616 if ((NULL != attestation_name) &&
617 (NULL != attr_value))
619 struct GNUNET_RECLAIM_Attestation *attestation =
620 GNUNET_RECLAIM_attestation_new (attestation_name,
621 GNUNET_RECLAIM_ATTESTATION_TYPE_JWT, // FIXME hardcoded
623 strlen (attr_value));
624 reclaim_op = GNUNET_RECLAIM_attestation_store (reclaim_handle,
633 if (list_attestations)
635 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
638 attr_iterator = GNUNET_RECLAIM_get_attributes_start (reclaim_handle,
651 attest_iter_cb (void *cls,
652 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
653 const struct GNUNET_RECLAIM_Attestation *attest)
658 const char *attest_type;
659 struct GNUNET_RECLAIM_AttributeListEntry *ale;
661 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&attestation,
663 attestation_exists = GNUNET_YES;
664 if (list_attestations)
666 attest_str = GNUNET_RECLAIM_attestation_value_to_string (attest->type,
669 attest_type = GNUNET_RECLAIM_attestation_number_to_typename (attest->type);
670 id = GNUNET_STRINGS_data_to_string_alloc (&attest->id, sizeof(attest->id));
672 "%s: ``%s'' (%s); ID: %s\n",
677 struct GNUNET_RECLAIM_AttributeList *attrs =
678 GNUNET_RECLAIM_attestation_get_attributes (attest);
683 for (ale = attrs->list_head; NULL != ale; ale = ale->next)
685 attr_str = GNUNET_RECLAIM_attribute_value_to_string (
686 ale->attribute->type,
693 "\t %s: %s\n", ale->attribute->name, attr_str);
694 GNUNET_free (attr_str);
696 GNUNET_RECLAIM_attribute_list_destroy (attrs);
700 GNUNET_RECLAIM_get_attestations_next (attest_iterator);
709 fprintf (stderr, "Ego %s not found\n", ego_name);
710 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
713 attestation = GNUNET_RECLAIM_ID_ZERO;
714 if (NULL != attestation_id)
715 GNUNET_STRINGS_string_to_data (attestation_id,
716 strlen (attestation_id),
717 &attestation, sizeof(attestation));
718 attestation_exists = GNUNET_NO;
721 ticket_iterator = GNUNET_RECLAIM_ticket_iteration_start (reclaim_handle,
734 GNUNET_CRYPTO_ecdsa_public_key_from_string (rp, strlen (rp), &rp_key)) )
736 fprintf (stderr, "%s is not a public key!\n", rp);
737 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
740 if (NULL != consume_ticket)
741 GNUNET_STRINGS_string_to_data (consume_ticket,
742 strlen (consume_ticket),
744 sizeof(struct GNUNET_RECLAIM_Ticket));
745 if (NULL != revoke_ticket)
746 GNUNET_STRINGS_string_to_data (revoke_ticket,
747 strlen (revoke_ticket),
749 sizeof(struct GNUNET_RECLAIM_Ticket));
751 attr_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
753 attest_iterator = GNUNET_RECLAIM_get_attestations_start (reclaim_handle,
760 attest_iter_finished,
766 static int init = GNUNET_YES;
770 struct GNUNET_IDENTITY_Ego *ego,
776 if (GNUNET_YES == init)
783 if (0 != strcmp (name, ego_name))
785 pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
793 const struct GNUNET_CONFIGURATION_Handle *c)
796 if (NULL == ego_name)
799 fprintf (stderr, _ ("Ego is required\n"));
803 if ((NULL == attr_value) && (NULL != attr_name))
806 fprintf (stderr, _ ("Attribute value missing!\n"));
810 if ((NULL == rp) && (NULL != issue_attrs))
813 fprintf (stderr, _ ("Requesting party key is required!\n"));
817 reclaim_handle = GNUNET_RECLAIM_connect (c);
819 identity_handle = GNUNET_IDENTITY_connect (c, &ego_cb, NULL);
824 main (int argc, char *const argv[])
826 exp_interval = GNUNET_TIME_UNIT_HOURS;
827 struct GNUNET_GETOPT_CommandLineOption options[] = {
828 GNUNET_GETOPT_option_string ('a',
831 gettext_noop ("Add an attribute NAME"),
833 GNUNET_GETOPT_option_string ('d',
836 gettext_noop ("Delete the attribute with ID"),
838 GNUNET_GETOPT_option_string ('V',
841 gettext_noop ("The attribute VALUE"),
843 GNUNET_GETOPT_option_string ('e',
846 gettext_noop ("The EGO to use"),
848 GNUNET_GETOPT_option_string ('r',
852 "Specify the relying party for issue"),
854 GNUNET_GETOPT_option_flag ('D',
856 gettext_noop ("List attributes for EGO"),
858 GNUNET_GETOPT_option_flag ('A',
860 gettext_noop ("List attestations for EGO"),
862 GNUNET_GETOPT_option_string ('I',
866 "Attestation to use for attribute"),
868 GNUNET_GETOPT_option_string ('N',
871 gettext_noop ("Attestation name"),
873 GNUNET_GETOPT_option_string ('i',
877 "Issue a ticket for a set of attributes separated by comma"),
879 GNUNET_GETOPT_option_string ('C',
882 gettext_noop ("Consume a ticket"),
884 GNUNET_GETOPT_option_string ('R',
887 gettext_noop ("Revoke a ticket"),
889 GNUNET_GETOPT_option_string ('t',
892 gettext_noop ("Type of attribute"),
894 GNUNET_GETOPT_option_flag ('T',
896 gettext_noop ("List tickets of ego"),
898 GNUNET_GETOPT_option_relative_time ('E',
902 "Expiration interval of the attribute"),
905 GNUNET_GETOPT_OPTION_END
907 if (GNUNET_OK != GNUNET_PROGRAM_run (argc,
910 _ ("re:claimID command line tool"),