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"
53 static char *attr_name;
58 static char *attr_value;
63 static char *issue_attrs;
68 static char *consume_ticket;
73 static char *type_str;
78 static char *revoke_ticket;
83 static int list_tickets;
88 static char *ego_name;
93 static struct GNUNET_IDENTITY_Handle *identity_handle;
98 static struct GNUNET_RECLAIM_Handle *reclaim_handle;
103 static struct GNUNET_RECLAIM_Operation *reclaim_op;
108 static struct GNUNET_RECLAIM_AttributeIterator *attr_iterator;
113 static struct GNUNET_RECLAIM_TicketIterator *ticket_iterator;
118 static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
123 static const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey;
128 static struct GNUNET_CRYPTO_EcdsaPublicKey rp_key;
133 static struct GNUNET_RECLAIM_Ticket ticket;
138 static struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list;
141 * Attribute expiration interval
143 static struct GNUNET_TIME_Relative exp_interval;
148 static struct GNUNET_SCHEDULER_Task *timeout;
153 static struct GNUNET_SCHEDULER_Task *cleanup_task;
158 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
163 static char *attr_delete;
166 * Claim object to delete
168 static struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr_to_delete;
171 do_cleanup (void *cls)
175 GNUNET_SCHEDULER_cancel (timeout);
176 if (NULL != reclaim_op)
177 GNUNET_RECLAIM_cancel (reclaim_op);
178 if (NULL != attr_iterator)
179 GNUNET_RECLAIM_get_attributes_stop (attr_iterator);
180 if (NULL != ticket_iterator)
181 GNUNET_RECLAIM_ticket_iteration_stop (ticket_iterator);
182 if (NULL != reclaim_handle)
183 GNUNET_RECLAIM_disconnect (reclaim_handle);
184 if (NULL != identity_handle)
185 GNUNET_IDENTITY_disconnect (identity_handle);
187 GNUNET_free (abe_key);
188 if (NULL != attr_list)
189 GNUNET_free (attr_list);
190 if (NULL != attr_to_delete)
191 GNUNET_free (attr_to_delete);
195 ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
199 if (NULL != ticket) {
200 ticket_str = GNUNET_STRINGS_data_to_string_alloc (
201 ticket, sizeof (struct GNUNET_RECLAIM_Ticket));
202 printf ("%s\n", ticket_str);
203 GNUNET_free (ticket_str);
205 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
209 store_attr_cont (void *cls, int32_t success, const char *emsg)
212 if (GNUNET_SYSERR == success) {
213 fprintf (stderr, "%s\n", emsg);
215 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
219 process_attrs (void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
220 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
224 const char *attr_type;
226 if (NULL == identity) {
228 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
235 value_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type, attr->data,
237 attr_type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr->type);
238 id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof (uint64_t));
239 fprintf (stdout, "Name: %s; Value: %s (%s); Version %u; ID: %s\n", attr->name,
240 value_str, attr_type, attr->version, id);
245 ticket_iter_err (void *cls)
247 ticket_iterator = NULL;
248 fprintf (stderr, "Failed to iterate over tickets\n");
249 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
253 ticket_iter_fin (void *cls)
255 ticket_iterator = NULL;
256 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
260 ticket_iter (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
265 aud = GNUNET_STRINGS_data_to_string_alloc (
266 &ticket->audience, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
267 ref = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof (uint64_t));
269 fprintf (stdout, "Ticket ID: %s | Audience: %s\n", ref, aud);
272 GNUNET_RECLAIM_ticket_iteration_next (ticket_iterator);
276 iter_error (void *cls)
278 attr_iterator = NULL;
279 fprintf (stderr, "Failed to iterate over attributes\n");
280 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
284 timeout_task (void *cls)
288 fprintf (stderr, "Timeout\n");
289 if (NULL == cleanup_task)
290 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
294 process_rvk (void *cls, int success, const char *msg)
297 if (GNUNET_OK != success) {
298 fprintf (stderr, "Revocation failed.\n");
301 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
306 process_delete (void *cls, int success, const char *msg)
309 if (GNUNET_OK != success) {
310 fprintf (stderr, "Deletion failed.\n");
313 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
318 iter_finished (void *cls)
324 attr_iterator = NULL;
326 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
331 reclaim_op = GNUNET_RECLAIM_ticket_issue (
332 reclaim_handle, pkey, &rp_key, attr_list, &ticket_issue_cb, NULL);
335 if (consume_ticket) {
336 reclaim_op = GNUNET_RECLAIM_ticket_consume (reclaim_handle, pkey, &ticket,
337 &process_attrs, NULL);
338 timeout = GNUNET_SCHEDULER_add_delayed (
339 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
340 &timeout_task, NULL);
344 reclaim_op = GNUNET_RECLAIM_ticket_revoke (reclaim_handle, pkey, &ticket,
349 if (NULL == attr_to_delete) {
350 fprintf (stdout, "No such attribute ``%s''\n", attr_delete);
353 reclaim_op = GNUNET_RECLAIM_attribute_delete (
354 reclaim_handle, pkey, attr_to_delete, &process_delete, NULL);
358 if (NULL == type_str)
359 type = GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING;
361 type = GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (type_str);
363 GNUNET_assert (GNUNET_SYSERR !=
364 GNUNET_RECLAIM_ATTRIBUTE_string_to_value (
365 type, attr_value, (void **)&data, &data_size));
369 claim->data_size = data_size;
372 GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name, type, data, data_size);
374 reclaim_op = GNUNET_RECLAIM_attribute_store (
375 reclaim_handle, pkey, claim, &exp_interval, &store_attr_cont, NULL);
380 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
384 iter_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
385 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
387 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
392 const char *attr_type;
394 if ((NULL != attr_name) && (NULL != claim)) {
395 if (0 == strcasecmp (attr_name, attr->name)) {
396 claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name, attr->type,
397 attr->data, attr->data_size);
399 } else if (issue_attrs) {
400 attrs_tmp = GNUNET_strdup (issue_attrs);
401 attr_str = strtok (attrs_tmp, ",");
402 while (NULL != attr_str) {
403 if (0 != strcasecmp (attr_str, attr->name)) {
404 attr_str = strtok (NULL, ",");
407 le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
408 le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (
409 attr->name, attr->type, attr->data, attr->data_size);
410 le->claim->version = attr->version;
411 le->claim->id = attr->id;
412 GNUNET_CONTAINER_DLL_insert (attr_list->list_head, attr_list->list_tail,
416 GNUNET_free (attrs_tmp);
417 } else if (attr_delete && (NULL == attr_to_delete)) {
418 label = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof (uint64_t));
419 if (0 == strcasecmp (attr_delete, label)) {
420 attr_to_delete = GNUNET_RECLAIM_ATTRIBUTE_claim_new (
421 attr->name, attr->type, attr->data, attr->data_size);
422 attr_to_delete->id = attr->id;
426 attr_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type, attr->data,
428 attr_type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr->type);
429 id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof (uint64_t));
430 fprintf (stdout, "Name: %s; Value: %s (%s); Version %u; ID: %s\n",
431 attr->name, attr_str, attr_type, attr->version, id);
434 GNUNET_RECLAIM_get_attributes_next (attr_iterator);
441 fprintf (stderr, "Ego %s not found\n", ego_name);
442 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
447 ticket_iterator = GNUNET_RECLAIM_ticket_iteration_start (
448 reclaim_handle, pkey, &ticket_iter_err, NULL, &ticket_iter, NULL,
449 &ticket_iter_fin, NULL);
454 GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (rp, strlen (rp), &rp_key))
456 fprintf (stderr, "%s is not a public key!\n", rp);
457 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
460 if (NULL != consume_ticket)
461 GNUNET_STRINGS_string_to_data (consume_ticket, strlen (consume_ticket),
463 sizeof (struct GNUNET_RECLAIM_Ticket));
464 if (NULL != revoke_ticket)
465 GNUNET_STRINGS_string_to_data (revoke_ticket, strlen (revoke_ticket),
467 sizeof (struct GNUNET_RECLAIM_Ticket));
469 attr_list = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
471 attr_iterator = GNUNET_RECLAIM_get_attributes_start (
472 reclaim_handle, pkey, &iter_error, NULL, &iter_cb, NULL, &iter_finished,
476 static int init = GNUNET_YES;
479 ego_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx,
483 if (GNUNET_YES == init) {
489 if (0 != strcmp (name, ego_name))
491 pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
496 run (void *cls, char *const *args, const char *cfgfile,
497 const struct GNUNET_CONFIGURATION_Handle *c)
500 if (NULL == ego_name) {
502 fprintf (stderr, _ ("Ego is required\n"));
506 if ((NULL == attr_value) && (NULL != attr_name)) {
508 fprintf (stderr, _ ("Attribute value missing!\n"));
512 if ((NULL == rp) && (NULL != issue_attrs)) {
514 fprintf (stderr, _ ("Requesting party key is required!\n"));
518 reclaim_handle = GNUNET_RECLAIM_connect (c);
520 identity_handle = GNUNET_IDENTITY_connect (c, &ego_cb, NULL);
525 main (int argc, char *const argv[])
527 exp_interval = GNUNET_TIME_UNIT_HOURS;
528 struct GNUNET_GETOPT_CommandLineOption options[] = {
530 GNUNET_GETOPT_option_string ('a', "add", "NAME",
531 gettext_noop ("Add an attribute NAME"),
533 GNUNET_GETOPT_option_string ('d', "delete", "ID",
534 gettext_noop ("Delete the attribute with ID"),
536 GNUNET_GETOPT_option_string ('V', "value", "VALUE",
537 gettext_noop ("The attribute VALUE"),
539 GNUNET_GETOPT_option_string ('e', "ego", "EGO",
540 gettext_noop ("The EGO to use"), &ego_name),
541 GNUNET_GETOPT_option_string (
542 'r', "rp", "RP", gettext_noop ("Specify the relying party for issue"),
544 GNUNET_GETOPT_option_flag (
545 'D', "dump", gettext_noop ("List attributes for EGO"), &list),
546 GNUNET_GETOPT_option_string (
547 'i', "issue", "A1,A2,...",
549 "Issue a ticket for a set of attributes separated by comma"),
551 GNUNET_GETOPT_option_string ('C', "consume", "TICKET",
552 gettext_noop ("Consume a ticket"),
554 GNUNET_GETOPT_option_string ('R', "revoke", "TICKET",
555 gettext_noop ("Revoke a ticket"),
557 GNUNET_GETOPT_option_string (
558 't', "type", "TYPE", gettext_noop ("Type of attribute"), &type_str),
559 GNUNET_GETOPT_option_flag (
560 'T', "tickets", gettext_noop ("List tickets of ego"), &list_tickets),
561 GNUNET_GETOPT_option_relative_time (
562 'E', "expiration", "INTERVAL",
563 gettext_noop ("Expiration interval of the attribute"), &exp_interval),
565 GNUNET_GETOPT_OPTION_END};
566 if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "gnunet-reclaim",
567 _ ("re:claimID command line tool"),
568 options, &run, NULL))