121f2b9639841d2c1fd0e10b9454342a2b03ef0f
[oweals/gnunet.git] / src / reclaim / gnunet-reclaim.c
1 /*
2    This file is part of GNUnet.
3    Copyright (C) 2012-2015 GNUnet e.V.
4
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.
9
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.
14
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/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 /**
21  * @author Martin Schanzenbach
22  * @file src/reclaim/gnunet-reclaim.c
23  * @brief Identity Provider utility
24  *
25  */
26 #include "platform.h"
27 #include <inttypes.h>
28
29 #include "gnunet_util_lib.h"
30
31 #include "gnunet_identity_service.h"
32 #include "gnunet_namestore_service.h"
33 #include "gnunet_reclaim_service.h"
34 #include "gnunet_signatures.h"
35 /**
36  * return value
37  */
38 static int ret;
39
40 /**
41  * List attribute flag
42  */
43 static int list;
44
45 /**
46  * List attestations flag
47  */
48 static int list_attestations;
49
50 /**
51  * Attestation ID string
52  */
53 static char *attestation_id;
54
55 /**
56  * Attestation ID
57  */
58 static struct GNUNET_RECLAIM_Identifier attestation;
59
60 /**
61  * Attestation name
62  */
63 static char *attestation_name;
64
65 /**
66  * Attestation exists
67  */
68 static int attestation_exists;
69
70 /**
71  * Relying party
72  */
73 static char *rp;
74
75 /**
76  * The attribute
77  */
78 static char *attr_name;
79
80 /**
81  * Attribute value
82  */
83 static char *attr_value;
84
85 /**
86  * Attributes to issue
87  */
88 static char *issue_attrs;
89
90 /**
91  * Ticket to consume
92  */
93 static char *consume_ticket;
94
95 /**
96  * Attribute type
97  */
98 static char *type_str;
99
100 /**
101  * Ticket to revoke
102  */
103 static char *revoke_ticket;
104
105 /**
106  * Ticket listing
107  */
108 static int list_tickets;
109
110 /**
111  * Ego name
112  */
113 static char *ego_name;
114
115 /**
116  * Identity handle
117  */
118 static struct GNUNET_IDENTITY_Handle *identity_handle;
119
120 /**
121  * reclaim handle
122  */
123 static struct GNUNET_RECLAIM_Handle *reclaim_handle;
124
125 /**
126  * reclaim operation
127  */
128 static struct GNUNET_RECLAIM_Operation *reclaim_op;
129
130 /**
131  * Attribute iterator
132  */
133 static struct GNUNET_RECLAIM_AttributeIterator *attr_iterator;
134
135 /**
136  * Attestation iterator
137  */
138 static struct GNUNET_RECLAIM_AttestationIterator *attest_iterator;
139
140
141 /**
142  * Ticket iterator
143  */
144 static struct GNUNET_RECLAIM_TicketIterator *ticket_iterator;
145
146 /**
147  * Master ABE key
148  */
149 static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
150
151 /**
152  * ego private key
153  */
154 static const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey;
155
156 /**
157  * rp public key
158  */
159 static struct GNUNET_CRYPTO_EcdsaPublicKey rp_key;
160
161 /**
162  * Ticket to consume
163  */
164 static struct GNUNET_RECLAIM_Ticket ticket;
165
166 /**
167  * Attribute list
168  */
169 static struct GNUNET_RECLAIM_AttributeList *attr_list;
170
171 /**
172  * Attribute expiration interval
173  */
174 static struct GNUNET_TIME_Relative exp_interval;
175
176 /**
177  * Timeout task
178  */
179 static struct GNUNET_SCHEDULER_Task *timeout;
180
181 /**
182  * Cleanup task
183  */
184 static struct GNUNET_SCHEDULER_Task *cleanup_task;
185
186 /**
187  * Claim to store
188  */
189 struct GNUNET_RECLAIM_Attribute *claim;
190
191 /**
192  * Claim to delete
193  */
194 static char *attr_delete;
195
196 /**
197  * Claim object to delete
198  */
199 static struct GNUNET_RECLAIM_Attribute *attr_to_delete;
200
201 static void
202 do_cleanup (void *cls)
203 {
204   cleanup_task = NULL;
205   if (NULL != timeout)
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);
219   if (NULL != abe_key)
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);
225 }
226
227
228 static void
229 ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
230 {
231   char *ticket_str;
232
233   reclaim_op = NULL;
234   if (NULL != ticket)
235   {
236     ticket_str =
237       GNUNET_STRINGS_data_to_string_alloc (ticket,
238                                            sizeof(
239                                              struct GNUNET_RECLAIM_Ticket));
240     printf ("%s\n", ticket_str);
241     GNUNET_free (ticket_str);
242   }
243   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
244 }
245
246
247 static void
248 store_cont (void *cls, int32_t success, const char *emsg)
249 {
250   reclaim_op = NULL;
251   if (GNUNET_SYSERR == success)
252   {
253     fprintf (stderr, "%s\n", emsg);
254   }
255   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
256 }
257
258
259 static void
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)
264 {
265   char *value_str;
266   char *id;
267   const char *attr_type;
268
269   if (NULL == identity)
270   {
271     reclaim_op = NULL;
272     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
273     return;
274   }
275   if (NULL == attr)
276   {
277     ret = 1;
278     return;
279   }
280   value_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
281                                                         attr->data,
282                                                         attr->data_size);
283   attr_type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
284   id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
285   fprintf (stdout,
286            "Name: %s; Value: %s (%s); Flag %u; ID: %s %s\n",
287            attr->name,
288            value_str,
289            attr_type,
290            attr->flag,
291            id,
292            (NULL == attest) ? "" : "ATTESTED");
293   GNUNET_free (id);
294 }
295
296
297 static void
298 ticket_iter_err (void *cls)
299 {
300   ticket_iterator = NULL;
301   fprintf (stderr, "Failed to iterate over tickets\n");
302   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
303 }
304
305
306 static void
307 ticket_iter_fin (void *cls)
308 {
309   ticket_iterator = NULL;
310   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
311 }
312
313
314 static void
315 ticket_iter (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
316 {
317   char *aud;
318   char *ref;
319   char *tkt;
320
321   aud =
322     GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
323                                          sizeof(struct
324                                                 GNUNET_CRYPTO_EcdsaPublicKey));
325   ref = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(ticket->rnd));
326   tkt =
327     GNUNET_STRINGS_data_to_string_alloc (ticket,
328                                          sizeof(struct GNUNET_RECLAIM_Ticket));
329   fprintf (stdout, "Ticket: %s | ID: %s | Audience: %s\n", tkt, ref, aud);
330   GNUNET_free (aud);
331   GNUNET_free (ref);
332   GNUNET_free (tkt);
333   GNUNET_RECLAIM_ticket_iteration_next (ticket_iterator);
334 }
335
336
337 static void
338 iter_error (void *cls)
339 {
340   attr_iterator = NULL;
341   attest_iterator = NULL;
342   fprintf (stderr, "Failed\n");
343
344   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
345 }
346
347
348 static void
349 timeout_task (void *cls)
350 {
351   timeout = NULL;
352   ret = 1;
353   fprintf (stderr, "Timeout\n");
354   if (NULL == cleanup_task)
355     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
356 }
357
358
359 static void
360 process_rvk (void *cls, int success, const char *msg)
361 {
362   reclaim_op = NULL;
363   if (GNUNET_OK != success)
364   {
365     fprintf (stderr, "Revocation failed.\n");
366     ret = 1;
367   }
368   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
369 }
370
371
372 static void
373 process_delete (void *cls, int success, const char *msg)
374 {
375   reclaim_op = NULL;
376   if (GNUNET_OK != success)
377   {
378     fprintf (stderr, "Deletion failed.\n");
379     ret = 1;
380   }
381   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
382 }
383
384
385 static void
386 iter_finished (void *cls)
387 {
388   char *data;
389   size_t data_size;
390   int type;
391
392   attr_iterator = NULL;
393   if (list)
394   {
395     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
396     return;
397   }
398
399   if (issue_attrs)
400   {
401     reclaim_op = GNUNET_RECLAIM_ticket_issue (reclaim_handle,
402                                               pkey,
403                                               &rp_key,
404                                               attr_list,
405                                               &ticket_issue_cb,
406                                               NULL);
407     return;
408   }
409   if (consume_ticket)
410   {
411     reclaim_op = GNUNET_RECLAIM_ticket_consume (reclaim_handle,
412                                                 pkey,
413                                                 &ticket,
414                                                 &process_attrs,
415                                                 NULL);
416     timeout = GNUNET_SCHEDULER_add_delayed (
417       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
418       &timeout_task,
419       NULL);
420     return;
421   }
422   if (revoke_ticket)
423   {
424     reclaim_op = GNUNET_RECLAIM_ticket_revoke (reclaim_handle,
425                                                pkey,
426                                                &ticket,
427                                                &process_rvk,
428                                                NULL);
429     return;
430   }
431   if (attr_delete)
432   {
433     if (NULL == attr_to_delete)
434     {
435       fprintf (stdout, "No such attribute ``%s''\n", attr_delete);
436       return;
437     }
438     reclaim_op = GNUNET_RECLAIM_attribute_delete (reclaim_handle,
439                                                   pkey,
440                                                   attr_to_delete,
441                                                   &process_delete,
442                                                   NULL);
443     return;
444   }
445   if (attr_name)
446   {
447     if (NULL == type_str)
448       type = GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING;
449     else
450       type = GNUNET_RECLAIM_attribute_typename_to_number (type_str);
451
452     GNUNET_assert (GNUNET_SYSERR !=
453                    GNUNET_RECLAIM_attribute_string_to_value (type,
454                                                              attr_value,
455                                                              (void **) &data,
456                                                              &data_size));
457     if (NULL != claim)
458     {
459       claim->type = type;
460       claim->data = data;
461       claim->data_size = data_size;
462     }
463     else
464     {
465       claim =
466         GNUNET_RECLAIM_attribute_new (attr_name, NULL, type, data, data_size);
467     }
468     if (NULL != attestation_id)
469     {
470       claim->attestation = attestation;
471     }
472     reclaim_op = GNUNET_RECLAIM_attribute_store (reclaim_handle,
473                                                  pkey,
474                                                  claim,
475                                                  &exp_interval,
476                                                  &store_cont,
477                                                  NULL);
478     GNUNET_free (data);
479     GNUNET_free (claim);
480     return;
481   }
482   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
483 }
484
485
486 static void
487 iter_cb (void *cls,
488          const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
489          const struct GNUNET_RECLAIM_Attribute *attr)
490 {
491   struct GNUNET_RECLAIM_AttributeListEntry *le;
492   char *attrs_tmp;
493   char *attr_str;
494   char *label;
495   char *id;
496   const char *attr_type;
497
498   if ((NULL != attr_name) && (NULL != claim))
499   {
500     if (0 == strcasecmp (attr_name, attr->name))
501     {
502       claim = GNUNET_RECLAIM_attribute_new (attr->name,
503                                             &attr->attestation,
504                                             attr->type,
505                                             attr->data,
506                                             attr->data_size);
507     }
508   }
509   else if (issue_attrs)
510   {
511     attrs_tmp = GNUNET_strdup (issue_attrs);
512     attr_str = strtok (attrs_tmp, ",");
513     while (NULL != attr_str)
514     {
515       if (0 != strcasecmp (attr_str, attr->name))
516       {
517         attr_str = strtok (NULL, ",");
518         continue;
519       }
520       le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
521       le->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
522                                                     &attr->attestation,
523                                                     attr->type,
524                                                     attr->data,
525                                                     attr->data_size);
526       le->attribute->flag = attr->flag;
527       le->attribute->id = attr->id;
528       GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
529                                    attr_list->list_tail,
530                                    le);
531       break;
532     }
533     GNUNET_free (attrs_tmp);
534   }
535   else if (attr_delete && (NULL == attr_to_delete))
536   {
537     label = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
538     if (0 == strcasecmp (attr_delete, label))
539     {
540       attr_to_delete = GNUNET_RECLAIM_attribute_new (attr->name,
541                                                      &attr->attestation,
542                                                      attr->type,
543                                                      attr->data,
544                                                      attr->data_size);
545       attr_to_delete->id = attr->id;
546     }
547     GNUNET_free (label);
548   }
549   else if (list)
550   {
551     attr_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
552                                                          attr->data,
553                                                          attr->data_size);
554     attr_type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
555     id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
556     if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attr->attestation))
557     {
558       fprintf (stdout,
559                "Name: %s; Value: %s (%s); Flag %u; ID: %s\n",
560                attr->name,
561                attr_str,
562                attr_type,
563                attr->flag,
564                id);
565     }
566     else
567     {
568       fprintf (stdout,
569                "Name: %s; Value: %s (%s); Flag %u; ID: %s\n",
570                attr->name,
571                attr_str,
572                attr_type,
573                attr->flag,
574                id);
575
576     }
577     GNUNET_free (id);
578   }
579   GNUNET_RECLAIM_get_attributes_next (attr_iterator);
580 }
581
582
583 static void
584 attest_iter_finished (void *cls)
585 {
586   attest_iterator = NULL;
587
588   // Add new attestation
589   if ((NULL != attestation_name) &&
590       (NULL != attr_value))
591   {
592     struct GNUNET_RECLAIM_Attestation *attestation =
593       GNUNET_RECLAIM_attestation_new (attestation_name,
594                                       GNUNET_RECLAIM_ATTESTATION_TYPE_JWT, // FIXME hardcoded
595                                       attr_value,
596                                       strlen (attr_value));
597     reclaim_op = GNUNET_RECLAIM_attestation_store (reclaim_handle,
598                                                    pkey,
599                                                    attestation,
600                                                    &exp_interval,
601                                                    store_cont,
602                                                    NULL);
603     return;
604
605   }
606   if (list_attestations)
607   {
608     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
609     return;
610   }
611   attr_iterator = GNUNET_RECLAIM_get_attributes_start (reclaim_handle,
612                                                        pkey,
613                                                        &iter_error,
614                                                        NULL,
615                                                        &iter_cb,
616                                                        NULL,
617                                                        &iter_finished,
618                                                        NULL);
619
620 }
621
622
623 static void
624 attest_iter_cb (void *cls,
625                 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
626                 const struct GNUNET_RECLAIM_Attestation *attest,
627                 const struct GNUNET_RECLAIM_AttributeList *attrs)
628 {
629   char *attest_str;
630   char *attr_str;
631   char *id;
632   const char *attest_type;
633   struct GNUNET_RECLAIM_AttributeListEntry *ale;
634
635   if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&attestation,
636                                                 &attest->id))
637     attestation_exists = GNUNET_YES;
638   if (list_attestations)
639   {
640     attest_str = GNUNET_RECLAIM_attestation_value_to_string (attest->type,
641                                                              attest->data,
642                                                              attest->data_size);
643     attest_type = GNUNET_RECLAIM_attestation_number_to_typename (attest->type);
644     id = GNUNET_STRINGS_data_to_string_alloc (&attest->id, sizeof(attest->id));
645     fprintf (stdout,
646              "Name: %s; Value: %s (%s); Flag %u; ID: %s\n",
647              attest->name,
648              attest_str,
649              attest_type,
650              attest->flag,
651              id);
652     if (NULL != attrs)
653     {
654       fprintf (stdout,
655                "\t Attributes:\n");
656       for (ale = attrs->list_head; NULL != ale; ale = ale->next)
657       {
658         attr_str = GNUNET_RECLAIM_attribute_value_to_string (ale->attribute->type,
659                                                              ale->attribute->data,
660                                                              ale->attribute->data_size);
661
662         fprintf (stdout,
663                  "\t %s: %s\n", ale->attribute->name, attr_str);
664         GNUNET_free (attr_str);
665       }
666     }
667     GNUNET_free (id);
668   }
669   GNUNET_RECLAIM_get_attestations_next (attest_iterator);
670 }
671
672
673 static void
674 start_process ()
675 {
676   if (NULL == pkey)
677   {
678     fprintf (stderr, "Ego %s not found\n", ego_name);
679     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
680     return;
681   }
682   attestation = GNUNET_RECLAIM_ID_ZERO;
683   if (NULL != attestation_id)
684     GNUNET_STRINGS_string_to_data (attestation_id,
685                                    strlen (attestation_id),
686                                    &attestation, sizeof(attestation));
687   attestation_exists = GNUNET_NO;
688   if (list_tickets)
689   {
690     ticket_iterator = GNUNET_RECLAIM_ticket_iteration_start (reclaim_handle,
691                                                              pkey,
692                                                              &ticket_iter_err,
693                                                              NULL,
694                                                              &ticket_iter,
695                                                              NULL,
696                                                              &ticket_iter_fin,
697                                                              NULL);
698     return;
699   }
700
701   if ((NULL != rp) &&
702       (GNUNET_OK !=
703        GNUNET_CRYPTO_ecdsa_public_key_from_string (rp, strlen (rp), &rp_key)) )
704   {
705     fprintf (stderr, "%s is not a public key!\n", rp);
706     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
707     return;
708   }
709   if (NULL != consume_ticket)
710     GNUNET_STRINGS_string_to_data (consume_ticket,
711                                    strlen (consume_ticket),
712                                    &ticket,
713                                    sizeof(struct GNUNET_RECLAIM_Ticket));
714   if (NULL != revoke_ticket)
715     GNUNET_STRINGS_string_to_data (revoke_ticket,
716                                    strlen (revoke_ticket),
717                                    &ticket,
718                                    sizeof(struct GNUNET_RECLAIM_Ticket));
719
720   attr_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
721   claim = NULL;
722   attest_iterator = GNUNET_RECLAIM_get_attestations_start (reclaim_handle,
723                                                            pkey,
724                                                            &iter_error,
725                                                            NULL,
726                                                            &attest_iter_cb,
727                                                            NULL,
728                                                            &
729                                                            attest_iter_finished,
730                                                            NULL);
731
732 }
733
734
735 static int init = GNUNET_YES;
736
737 static void
738 ego_cb (void *cls,
739         struct GNUNET_IDENTITY_Ego *ego,
740         void **ctx,
741         const char *name)
742 {
743   if (NULL == name)
744   {
745     if (GNUNET_YES == init)
746     {
747       init = GNUNET_NO;
748       start_process ();
749     }
750     return;
751   }
752   if (0 != strcmp (name, ego_name))
753     return;
754   pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
755 }
756
757
758 static void
759 run (void *cls,
760      char *const *args,
761      const char *cfgfile,
762      const struct GNUNET_CONFIGURATION_Handle *c)
763 {
764   ret = 0;
765   if (NULL == ego_name)
766   {
767     ret = 1;
768     fprintf (stderr, _ ("Ego is required\n"));
769     return;
770   }
771
772   if ((NULL == attr_value) && (NULL != attr_name))
773   {
774     ret = 1;
775     fprintf (stderr, _ ("Attribute value missing!\n"));
776     return;
777   }
778
779   if ((NULL == rp) && (NULL != issue_attrs))
780   {
781     ret = 1;
782     fprintf (stderr, _ ("Requesting party key is required!\n"));
783     return;
784   }
785
786   reclaim_handle = GNUNET_RECLAIM_connect (c);
787   // Get Ego
788   identity_handle = GNUNET_IDENTITY_connect (c, &ego_cb, NULL);
789 }
790
791
792 int
793 main (int argc, char *const argv[])
794 {
795   exp_interval = GNUNET_TIME_UNIT_HOURS;
796   struct GNUNET_GETOPT_CommandLineOption options[] = {
797     GNUNET_GETOPT_option_string ('a',
798                                  "add",
799                                  "NAME",
800                                  gettext_noop ("Add an attribute NAME"),
801                                  &attr_name),
802     GNUNET_GETOPT_option_string ('d',
803                                  "delete",
804                                  "ID",
805                                  gettext_noop ("Delete the attribute with ID"),
806                                  &attr_delete),
807     GNUNET_GETOPT_option_string ('V',
808                                  "value",
809                                  "VALUE",
810                                  gettext_noop ("The attribute VALUE"),
811                                  &attr_value),
812     GNUNET_GETOPT_option_string ('e',
813                                  "ego",
814                                  "EGO",
815                                  gettext_noop ("The EGO to use"),
816                                  &ego_name),
817     GNUNET_GETOPT_option_string ('r',
818                                  "rp",
819                                  "RP",
820                                  gettext_noop (
821                                    "Specify the relying party for issue"),
822                                  &rp),
823     GNUNET_GETOPT_option_flag ('D',
824                                "dump",
825                                gettext_noop ("List attributes for EGO"),
826                                &list),
827     GNUNET_GETOPT_option_flag ('A',
828                                "attestations",
829                                gettext_noop ("List attestations for EGO"),
830                                &list_attestations),
831     GNUNET_GETOPT_option_string ('I',
832                                  "Attestation ID",
833                                  "ATTESTATION_ID",
834                                  gettext_noop (
835                                    "Attestation to use for attribute"),
836                                  &attestation_id),
837     GNUNET_GETOPT_option_string ('N',
838                                  "attestation-name",
839                                  "NAME",
840                                  gettext_noop ("Attestation name"),
841                                  &attestation_name),
842     GNUNET_GETOPT_option_string ('i',
843                                  "issue",
844                                  "A1,A2,...",
845                                  gettext_noop (
846                                    "Issue a ticket for a set of attributes separated by comma"),
847                                  &issue_attrs),
848     GNUNET_GETOPT_option_string ('C',
849                                  "consume",
850                                  "TICKET",
851                                  gettext_noop ("Consume a ticket"),
852                                  &consume_ticket),
853     GNUNET_GETOPT_option_string ('R',
854                                  "revoke",
855                                  "TICKET",
856                                  gettext_noop ("Revoke a ticket"),
857                                  &revoke_ticket),
858     GNUNET_GETOPT_option_string ('t',
859                                  "type",
860                                  "TYPE",
861                                  gettext_noop ("Type of attribute"),
862                                  &type_str),
863     GNUNET_GETOPT_option_flag ('T',
864                                "tickets",
865                                gettext_noop ("List tickets of ego"),
866                                &list_tickets),
867     GNUNET_GETOPT_option_relative_time ('E',
868                                         "expiration",
869                                         "INTERVAL",
870                                         gettext_noop (
871                                           "Expiration interval of the attribute"),
872                                         &exp_interval),
873
874     GNUNET_GETOPT_OPTION_END
875   };
876   if (GNUNET_OK != GNUNET_PROGRAM_run (argc,
877                                        argv,
878                                        "gnunet-reclaim",
879                                        _ ("re:claimID command line tool"),
880                                        options,
881                                        &run,
882                                        NULL))
883     return 1;
884   else
885     return ret;
886 }