use NULL value in load_path_suffix to NOT load any files
[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  * Relying party
47  */
48 static char *rp;
49
50 /**
51  * The attribute
52  */
53 static char *attr_name;
54
55 /**
56  * Attribute value
57  */
58 static char *attr_value;
59
60 /**
61  * Attributes to issue
62  */
63 static char *issue_attrs;
64
65 /**
66  * Ticket to consume
67  */
68 static char *consume_ticket;
69
70 /**
71  * Attribute type
72  */
73 static char *type_str;
74
75 /**
76  * Ticket to revoke
77  */
78 static char *revoke_ticket;
79
80 /**
81  * Ticket listing
82  */
83 static int list_tickets;
84
85 /**
86  * Ego name
87  */
88 static char *ego_name;
89
90 /**
91  * Identity handle
92  */
93 static struct GNUNET_IDENTITY_Handle *identity_handle;
94
95 /**
96  * reclaim handle
97  */
98 static struct GNUNET_RECLAIM_Handle *reclaim_handle;
99
100 /**
101  * reclaim operation
102  */
103 static struct GNUNET_RECLAIM_Operation *reclaim_op;
104
105 /**
106  * Attribute iterator
107  */
108 static struct GNUNET_RECLAIM_AttributeIterator *attr_iterator;
109
110 /**
111  * Ticket iterator
112  */
113 static struct GNUNET_RECLAIM_TicketIterator *ticket_iterator;
114
115 /**
116  * Master ABE key
117  */
118 static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
119
120 /**
121  * ego private key
122  */
123 static const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey;
124
125 /**
126  * rp public key
127  */
128 static struct GNUNET_CRYPTO_EcdsaPublicKey rp_key;
129
130 /**
131  * Ticket to consume
132  */
133 static struct GNUNET_RECLAIM_Ticket ticket;
134
135 /**
136  * Attribute list
137  */
138 static struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list;
139
140 /**
141  * Attribute expiration interval
142  */
143 static struct GNUNET_TIME_Relative exp_interval;
144
145 /**
146  * Timeout task
147  */
148 static struct GNUNET_SCHEDULER_Task *timeout;
149
150 /**
151  * Cleanup task
152  */
153 static struct GNUNET_SCHEDULER_Task *cleanup_task;
154
155 /**
156  * Claim to store
157  */
158 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
159
160 /**
161  * Claim to delete
162  */
163 static char *attr_delete;
164
165 /**
166  * Claim object to delete
167  */
168 static struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr_to_delete;
169
170 static void
171 do_cleanup (void *cls)
172 {
173   cleanup_task = NULL;
174   if (NULL != timeout)
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);
186   if (NULL != abe_key)
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);
192 }
193
194
195 static void
196 ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
197 {
198   char *ticket_str;
199
200   reclaim_op = NULL;
201   if (NULL != ticket)
202   {
203     ticket_str =
204       GNUNET_STRINGS_data_to_string_alloc (ticket,
205                                            sizeof(
206                                              struct GNUNET_RECLAIM_Ticket));
207     printf ("%s\n", ticket_str);
208     GNUNET_free (ticket_str);
209   }
210   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
211 }
212
213
214 static void
215 store_attr_cont (void *cls, int32_t success, const char *emsg)
216 {
217   reclaim_op = NULL;
218   if (GNUNET_SYSERR == success)
219   {
220     fprintf (stderr, "%s\n", emsg);
221   }
222   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
223 }
224
225
226 static void
227 process_attrs (void *cls,
228                const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
229                const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
230                const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest, 
231                const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
232 {
233   char *value_str;
234   char *id;
235   const char *attr_type;
236
237   if (NULL == identity)
238   {
239     reclaim_op = NULL;
240     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
241     return;
242   }
243   if (NULL == attr)
244   {
245     ret = 1;
246     return;
247   }
248   value_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
249                                                         attr->data,
250                                                         attr->data_size);
251   attr_type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr->type);
252   id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(uint64_t));
253   fprintf (stdout,
254            "Name: %s; Value: %s (%s); Version %u; ID: %s\n",
255            attr->name,
256            value_str,
257            attr_type,
258            attr->flag,
259            id);
260   GNUNET_free (id);
261 }
262
263
264 static void
265 ticket_iter_err (void *cls)
266 {
267   ticket_iterator = NULL;
268   fprintf (stderr, "Failed to iterate over tickets\n");
269   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
270 }
271
272
273 static void
274 ticket_iter_fin (void *cls)
275 {
276   ticket_iterator = NULL;
277   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
278 }
279
280
281 static void
282 ticket_iter (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
283 {
284   char *aud;
285   char *ref;
286   char *tkt;
287
288   aud =
289     GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
290                                          sizeof(struct
291                                                 GNUNET_CRYPTO_EcdsaPublicKey));
292   ref = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(uint64_t));
293   tkt =
294     GNUNET_STRINGS_data_to_string_alloc (ticket,
295                                          sizeof(struct GNUNET_RECLAIM_Ticket));
296   fprintf (stdout, "Ticket: %s | ID: %s | Audience: %s\n", tkt, ref, aud);
297   GNUNET_free (aud);
298   GNUNET_free (ref);
299   GNUNET_free (tkt);
300   GNUNET_RECLAIM_ticket_iteration_next (ticket_iterator);
301 }
302
303
304 static void
305 iter_error (void *cls)
306 {
307   attr_iterator = NULL;
308   fprintf (stderr, "Failed to iterate over attributes\n");
309   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
310 }
311
312
313 static void
314 timeout_task (void *cls)
315 {
316   timeout = NULL;
317   ret = 1;
318   fprintf (stderr, "Timeout\n");
319   if (NULL == cleanup_task)
320     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
321 }
322
323
324 static void
325 process_rvk (void *cls, int success, const char *msg)
326 {
327   reclaim_op = NULL;
328   if (GNUNET_OK != success)
329   {
330     fprintf (stderr, "Revocation failed.\n");
331     ret = 1;
332   }
333   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
334 }
335
336
337 static void
338 process_delete (void *cls, int success, const char *msg)
339 {
340   reclaim_op = NULL;
341   if (GNUNET_OK != success)
342   {
343     fprintf (stderr, "Deletion failed.\n");
344     ret = 1;
345   }
346   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
347 }
348
349
350 static void
351 iter_finished (void *cls)
352 {
353   char *data;
354   size_t data_size;
355   int type;
356
357   attr_iterator = NULL;
358   if (list)
359   {
360     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
361     return;
362   }
363
364   if (issue_attrs)
365   {
366     reclaim_op = GNUNET_RECLAIM_ticket_issue (reclaim_handle,
367                                               pkey,
368                                               &rp_key,
369                                               attr_list,
370                                               &ticket_issue_cb,
371                                               NULL);
372     return;
373   }
374   if (consume_ticket)
375   {
376     reclaim_op = GNUNET_RECLAIM_ticket_consume (reclaim_handle,
377                                                 pkey,
378                                                 &ticket,
379                                                 &process_attrs,
380                                                 NULL);
381     timeout = GNUNET_SCHEDULER_add_delayed (
382       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
383       &timeout_task,
384       NULL);
385     return;
386   }
387   if (revoke_ticket)
388   {
389     reclaim_op = GNUNET_RECLAIM_ticket_revoke (reclaim_handle,
390                                                pkey,
391                                                &ticket,
392                                                &process_rvk,
393                                                NULL);
394     return;
395   }
396   if (attr_delete)
397   {
398     if (NULL == attr_to_delete)
399     {
400       fprintf (stdout, "No such attribute ``%s''\n", attr_delete);
401       return;
402     }
403     reclaim_op = GNUNET_RECLAIM_attribute_delete (reclaim_handle,
404                                                   pkey,
405                                                   attr_to_delete,
406                                                   &process_delete,
407                                                   NULL);
408     return;
409   }
410   if (attr_name)
411   {
412     if (NULL == type_str)
413       type = GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING;
414     else
415       type = GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (type_str);
416
417     GNUNET_assert (GNUNET_SYSERR !=
418                    GNUNET_RECLAIM_ATTRIBUTE_string_to_value (type,
419                                                              attr_value,
420                                                              (void **) &data,
421                                                              &data_size));
422     if (NULL != claim)
423     {
424       claim->type = type;
425       claim->data = data;
426       claim->data_size = data_size;
427     }
428     else
429     {
430       claim =
431         GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name, type, data, data_size);
432     }
433     reclaim_op = GNUNET_RECLAIM_attribute_store (reclaim_handle,
434                                                  pkey,
435                                                  claim,
436                                                  &exp_interval,
437                                                  &store_attr_cont,
438                                                  NULL);
439     GNUNET_free (data);
440     GNUNET_free (claim);
441     return;
442   }
443   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
444 }
445
446
447 static void
448 iter_cb (void *cls,
449          const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
450          const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
451          const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
452          const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
453 {
454   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
455   char *attrs_tmp;
456   char *attr_str;
457   char *label;
458   char *id;
459   const char *attr_type;
460
461   if ((NULL != attr_name) && (NULL != claim))
462   {
463     if (0 == strcasecmp (attr_name, attr->name))
464     {
465       claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name,
466                                                   attr->type,
467                                                   attr->data,
468                                                   attr->data_size);
469     }
470   }
471   else if (issue_attrs)
472   {
473     attrs_tmp = GNUNET_strdup (issue_attrs);
474     attr_str = strtok (attrs_tmp, ",");
475     while (NULL != attr_str)
476     {
477       if (0 != strcasecmp (attr_str, attr->name))
478       {
479         attr_str = strtok (NULL, ",");
480         continue;
481       }
482       le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
483       le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name,
484                                                       attr->type,
485                                                       attr->data,
486                                                       attr->data_size);
487       le->claim->flag = attr->flag;
488       le->claim->id = attr->id;
489       GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
490                                    attr_list->list_tail,
491                                    le);
492       break;
493     }
494     GNUNET_free (attrs_tmp);
495   }
496   else if (attr_delete && (NULL == attr_to_delete))
497   {
498     label = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(uint64_t));
499     if (0 == strcasecmp (attr_delete, label))
500     {
501       attr_to_delete = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name,
502                                                            attr->type,
503                                                            attr->data,
504                                                            attr->data_size);
505       attr_to_delete->id = attr->id;
506     }
507     GNUNET_free (label);
508   }
509   else if (list)
510   {
511     attr_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
512                                                          attr->data,
513                                                          attr->data_size);
514     attr_type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr->type);
515     id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(uint64_t));
516     fprintf (stdout,
517              "Name: %s; Value: %s (%s); Version %u; ID: %s\n",
518              attr->name,
519              attr_str,
520              attr_type,
521              attr->flag,
522              id);
523     GNUNET_free (id);
524   }
525   GNUNET_RECLAIM_get_attributes_next (attr_iterator);
526 }
527
528
529 static void
530 start_process ()
531 {
532   if (NULL == pkey)
533   {
534     fprintf (stderr, "Ego %s not found\n", ego_name);
535     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
536     return;
537   }
538
539   if (list_tickets)
540   {
541     ticket_iterator = GNUNET_RECLAIM_ticket_iteration_start (reclaim_handle,
542                                                              pkey,
543                                                              &ticket_iter_err,
544                                                              NULL,
545                                                              &ticket_iter,
546                                                              NULL,
547                                                              &ticket_iter_fin,
548                                                              NULL);
549     return;
550   }
551
552   if ((NULL != rp) &&
553       (GNUNET_OK !=
554        GNUNET_CRYPTO_ecdsa_public_key_from_string (rp, strlen (rp), &rp_key)) )
555   {
556     fprintf (stderr, "%s is not a public key!\n", rp);
557     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
558     return;
559   }
560   if (NULL != consume_ticket)
561     GNUNET_STRINGS_string_to_data (consume_ticket,
562                                    strlen (consume_ticket),
563                                    &ticket,
564                                    sizeof(struct GNUNET_RECLAIM_Ticket));
565   if (NULL != revoke_ticket)
566     GNUNET_STRINGS_string_to_data (revoke_ticket,
567                                    strlen (revoke_ticket),
568                                    &ticket,
569                                    sizeof(struct GNUNET_RECLAIM_Ticket));
570
571   attr_list = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
572   claim = NULL;
573   attr_iterator = GNUNET_RECLAIM_get_attributes_start (reclaim_handle,
574                                                        pkey,
575                                                        &iter_error,
576                                                        NULL,
577                                                        &iter_cb,
578                                                        NULL,
579                                                        &iter_finished,
580                                                        NULL);
581 }
582
583
584 static int init = GNUNET_YES;
585
586 static void
587 ego_cb (void *cls,
588         struct GNUNET_IDENTITY_Ego *ego,
589         void **ctx,
590         const char *name)
591 {
592   if (NULL == name)
593   {
594     if (GNUNET_YES == init)
595     {
596       init = GNUNET_NO;
597       start_process ();
598     }
599     return;
600   }
601   if (0 != strcmp (name, ego_name))
602     return;
603   pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
604 }
605
606
607 static void
608 run (void *cls,
609      char *const *args,
610      const char *cfgfile,
611      const struct GNUNET_CONFIGURATION_Handle *c)
612 {
613   ret = 0;
614   if (NULL == ego_name)
615   {
616     ret = 1;
617     fprintf (stderr, _ ("Ego is required\n"));
618     return;
619   }
620
621   if ((NULL == attr_value) && (NULL != attr_name))
622   {
623     ret = 1;
624     fprintf (stderr, _ ("Attribute value missing!\n"));
625     return;
626   }
627
628   if ((NULL == rp) && (NULL != issue_attrs))
629   {
630     ret = 1;
631     fprintf (stderr, _ ("Requesting party key is required!\n"));
632     return;
633   }
634
635   reclaim_handle = GNUNET_RECLAIM_connect (c);
636   // Get Ego
637   identity_handle = GNUNET_IDENTITY_connect (c, &ego_cb, NULL);
638 }
639
640
641 int
642 main (int argc, char *const argv[])
643 {
644   exp_interval = GNUNET_TIME_UNIT_HOURS;
645   struct GNUNET_GETOPT_CommandLineOption options[] = {
646     GNUNET_GETOPT_option_string ('a',
647                                  "add",
648                                  "NAME",
649                                  gettext_noop ("Add an attribute NAME"),
650                                  &attr_name),
651     GNUNET_GETOPT_option_string ('d',
652                                  "delete",
653                                  "ID",
654                                  gettext_noop ("Delete the attribute with ID"),
655                                  &attr_delete),
656     GNUNET_GETOPT_option_string ('V',
657                                  "value",
658                                  "VALUE",
659                                  gettext_noop ("The attribute VALUE"),
660                                  &attr_value),
661     GNUNET_GETOPT_option_string ('e',
662                                  "ego",
663                                  "EGO",
664                                  gettext_noop ("The EGO to use"),
665                                  &ego_name),
666     GNUNET_GETOPT_option_string ('r',
667                                  "rp",
668                                  "RP",
669                                  gettext_noop (
670                                    "Specify the relying party for issue"),
671                                  &rp),
672     GNUNET_GETOPT_option_flag ('D',
673                                "dump",
674                                gettext_noop ("List attributes for EGO"),
675                                &list),
676     GNUNET_GETOPT_option_string (
677       'i',
678       "issue",
679       "A1,A2,...",
680       gettext_noop (
681         "Issue a ticket for a set of attributes separated by comma"),
682       &issue_attrs),
683     GNUNET_GETOPT_option_string ('C',
684                                  "consume",
685                                  "TICKET",
686                                  gettext_noop ("Consume a ticket"),
687                                  &consume_ticket),
688     GNUNET_GETOPT_option_string ('R',
689                                  "revoke",
690                                  "TICKET",
691                                  gettext_noop ("Revoke a ticket"),
692                                  &revoke_ticket),
693     GNUNET_GETOPT_option_string ('t',
694                                  "type",
695                                  "TYPE",
696                                  gettext_noop ("Type of attribute"),
697                                  &type_str),
698     GNUNET_GETOPT_option_flag ('T',
699                                "tickets",
700                                gettext_noop ("List tickets of ego"),
701                                &list_tickets),
702     GNUNET_GETOPT_option_relative_time ('E',
703                                         "expiration",
704                                         "INTERVAL",
705                                         gettext_noop (
706                                           "Expiration interval of the attribute"),
707                                         &exp_interval),
708
709     GNUNET_GETOPT_OPTION_END
710   };
711   if (GNUNET_OK != GNUNET_PROGRAM_run (argc,
712                                        argv,
713                                        "gnunet-reclaim",
714                                        _ ("re:claimID command line tool"),
715                                        options,
716                                        &run,
717                                        NULL))
718     return 1;
719   else
720     return ret;
721 }