RECLAIM: improve help
[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
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_namestore_service.h"
30 #include "gnunet_reclaim_service.h"
31 #include "gnunet_identity_service.h"
32 #include "gnunet_signatures.h"
33
34 /**
35  * return value
36  */
37 static int ret;
38
39 /**
40  * List attribute flag
41  */
42 static int list;
43
44 /**
45  * Relying party
46  */
47 static char* rp;
48
49 /**
50  * The attribute
51  */
52 static char* attr_name;
53
54 /**
55  * Attribute value
56  */
57 static char* attr_value;
58
59 /**
60  * Attributes to issue
61  */
62 static char* issue_attrs;
63
64 /**
65  * Ticket to consume
66  */
67 static char* consume_ticket;
68
69 /**
70  * Attribute type
71  */
72 static char* type_str;
73
74 /**
75  * Ticket to revoke
76  */
77 static char* revoke_ticket;
78
79 /**
80  * Ego name
81  */
82 static char* ego_name;
83
84 /**
85  * Identity handle
86  */
87 static struct GNUNET_IDENTITY_Handle *identity_handle;
88
89 /**
90  * reclaim handle
91  */
92 static struct GNUNET_RECLAIM_Handle *reclaim_handle;
93
94 /**
95  * reclaim operation
96  */
97 static struct GNUNET_RECLAIM_Operation *reclaim_op;
98
99 /**
100  * Attribute iterator
101  */
102 static struct GNUNET_RECLAIM_AttributeIterator *attr_iterator;
103
104 /**
105  * Master ABE key
106  */
107 static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
108
109 /**
110  * ego private key
111  */
112 static const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey;
113
114 /**
115  * rp public key
116  */
117 static struct GNUNET_CRYPTO_EcdsaPublicKey rp_key;
118
119 /**
120  * Ticket to consume
121  */
122 static struct GNUNET_RECLAIM_Ticket ticket;
123
124 /**
125  * Attribute list
126  */
127 static struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list;
128
129 /**
130  * Attribute expiration interval
131  */
132 static struct GNUNET_TIME_Relative exp_interval;
133
134 /**
135  * Timeout task
136  */
137 static struct GNUNET_SCHEDULER_Task *timeout;
138
139 /**
140  * Cleanup task
141  */
142 static struct GNUNET_SCHEDULER_Task *cleanup_task;
143
144 /**
145  * Claim to store
146  */
147 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
148
149 static void
150 do_cleanup(void *cls)
151 {
152   cleanup_task = NULL;
153   if (NULL != timeout)
154     GNUNET_SCHEDULER_cancel (timeout);
155   if (NULL != reclaim_op)
156     GNUNET_RECLAIM_cancel (reclaim_op);
157   if (NULL != attr_iterator)
158     GNUNET_RECLAIM_get_attributes_stop (attr_iterator);
159   if (NULL != reclaim_handle)
160     GNUNET_RECLAIM_disconnect (reclaim_handle);
161   if (NULL != identity_handle)
162     GNUNET_IDENTITY_disconnect (identity_handle);
163   if (NULL != abe_key)
164     GNUNET_free (abe_key);
165   if (NULL != attr_list)
166     GNUNET_free (attr_list);
167 }
168
169 static void
170 ticket_issue_cb (void* cls,
171                  const struct GNUNET_RECLAIM_Ticket *ticket)
172 {
173   char* ticket_str;
174   reclaim_op = NULL;
175   if (NULL != ticket) {
176     ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
177                                                       sizeof (struct GNUNET_RECLAIM_Ticket));
178     printf("%s\n",
179            ticket_str);
180     GNUNET_free (ticket_str);
181   }
182   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
183 }
184
185 static void
186 store_attr_cont (void *cls,
187                  int32_t success,
188                  const char*emsg)
189 {
190   reclaim_op = NULL;
191   if (GNUNET_SYSERR == success) {
192     fprintf (stderr,
193              "%s\n", emsg);
194   }
195   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
196 }
197
198 static void
199 process_attrs (void *cls,
200          const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
201          const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
202 {
203   char *value_str;
204   const char* attr_type;
205
206   if (NULL == identity)
207   {
208     reclaim_op = NULL;
209     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
210     return;
211   }
212   if (NULL == attr)
213   {
214     ret = 1;
215     return;
216   }
217   value_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
218                                                         attr->data,
219                                                         attr->data_size);
220   attr_type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr->type);
221   fprintf (stdout,
222            "%s: %s [%s,v%u,id=%lu]\n",
223            attr->name, value_str, attr_type, attr->version, attr->id);
224 }
225
226
227 static void
228 iter_error (void *cls)
229 {
230   attr_iterator = NULL;
231   fprintf (stderr,
232            "Failed to iterate over attributes\n");
233   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
234 }
235
236 static void
237 timeout_task (void *cls)
238 {
239   timeout = NULL;
240   ret = 1;
241   fprintf (stderr,
242            "Timeout\n");
243   if (NULL == cleanup_task)
244     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
245 }
246
247 static void
248 process_rvk (void *cls, int success, const char* msg)
249 {
250   reclaim_op = NULL;
251   if (GNUNET_OK != success)
252   {
253     fprintf (stderr,
254              "Revocation failed.\n");
255     ret = 1;
256   }
257   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
258 }
259
260 static void
261 iter_finished (void *cls)
262 {
263   char *data;
264   size_t data_size;
265   int type;
266
267   attr_iterator = NULL;
268   if (list)
269   {
270     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
271     return;
272   }
273
274   if (issue_attrs)
275   {
276     reclaim_op = GNUNET_RECLAIM_ticket_issue (reclaim_handle,
277                                               pkey,
278                                               &rp_key,
279                                               attr_list,
280                                               &ticket_issue_cb,
281                                               NULL);
282     return;
283   }
284   if (consume_ticket)
285   {
286     reclaim_op = GNUNET_RECLAIM_ticket_consume (reclaim_handle,
287                                                 pkey,
288                                                 &ticket,
289                                                 &process_attrs,
290                                                 NULL);
291     timeout = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10),
292                                             &timeout_task,
293                                             NULL);
294     return;
295   }
296   if (revoke_ticket)
297   {
298     reclaim_op = GNUNET_RECLAIM_ticket_revoke (reclaim_handle,
299                                                pkey,
300                                                &ticket,
301                                                &process_rvk,
302                                                NULL);
303     return;
304   }
305   if (attr_name)
306   {
307     if (NULL == type_str)
308       type = GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING;
309     else
310       type = GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (type_str);
311
312     GNUNET_assert (GNUNET_SYSERR != GNUNET_RECLAIM_ATTRIBUTE_string_to_value (type,
313                                                                               attr_value,
314                                                                               (void**)&data,
315                                                                               &data_size));
316     if (NULL != claim)
317     {
318       claim->type = type;
319       claim->data = data;
320       claim->data_size = data_size;
321     }
322     else
323     {
324       claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name,
325                                                   type,
326                                                   data,
327                                                   data_size);
328     }
329     reclaim_op = GNUNET_RECLAIM_attribute_store (reclaim_handle,
330                                                  pkey,
331                                                  claim,
332                                                  &exp_interval,
333                                                  &store_attr_cont,
334                                                  NULL);
335     GNUNET_free (data);
336     GNUNET_free (claim);
337     return;
338   }
339   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
340 }
341
342 static void
343 iter_cb (void *cls,
344          const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
345          const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
346 {
347   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
348   char *attrs_tmp;
349   char *attr_str;
350   const char *attr_type;
351
352   if ((NULL != attr_name) && (NULL != claim))
353   {
354     if (0 == strcasecmp (attr_name, attr->name))
355     {
356       claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name,
357                                                             attr->type,
358                                                             attr->data,
359                                                             attr->data_size);
360     }
361   }
362   else if (issue_attrs)
363   {
364     attrs_tmp = GNUNET_strdup (issue_attrs);
365     attr_str = strtok (attrs_tmp, ",");
366     while (NULL != attr_str) {
367       if (0 != strcasecmp (attr_str, attr->name)) {
368         attr_str = strtok (NULL, ",");
369         continue;
370       }
371       le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
372       le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name,
373                                                       attr->type,
374                                                       attr->data,
375                                                       attr->data_size);
376       le->claim->version = attr->version;
377       le->claim->id = attr->id;
378       GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
379                                    attr_list->list_tail,
380                                    le);
381       break;
382     }
383     GNUNET_free (attrs_tmp);
384   }
385   else if (list)
386   {
387     attr_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
388                                                          attr->data,
389                                                          attr->data_size);
390     attr_type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr->type);
391     fprintf (stdout,
392              "%s: %s [%s,v%u,id=%lu]\n",
393              attr->name, attr_str, attr_type, attr->version, attr->id);
394   }
395   GNUNET_RECLAIM_get_attributes_next (attr_iterator);
396 }
397
398 static void
399 start_get_attributes ()
400 {
401   if (NULL == pkey)
402   {
403     fprintf (stderr,
404              "Ego %s not found\n", ego_name);
405     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
406     return;
407   }
408
409   if (NULL != rp)
410     GNUNET_CRYPTO_ecdsa_public_key_from_string (rp,
411                                                 strlen (rp),
412                                                 &rp_key);
413   if (NULL != consume_ticket)
414     GNUNET_STRINGS_string_to_data (consume_ticket,
415                                    strlen (consume_ticket),
416                                    &ticket,
417                                    sizeof (struct GNUNET_RECLAIM_Ticket));
418   if (NULL != revoke_ticket)
419     GNUNET_STRINGS_string_to_data (revoke_ticket,
420                                    strlen (revoke_ticket),
421                                    &ticket,
422                                    sizeof (struct GNUNET_RECLAIM_Ticket));
423
424   attr_list = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
425   claim = NULL;
426   attr_iterator = GNUNET_RECLAIM_get_attributes_start (reclaim_handle,
427                                                        pkey,
428                                                        &iter_error,
429                                                        NULL,
430                                                        &iter_cb,
431                                                        NULL,
432                                                        &iter_finished,
433                                                        NULL);
434
435
436 }
437
438 static int init = GNUNET_YES;
439
440 static void
441 ego_cb (void *cls,
442         struct GNUNET_IDENTITY_Ego *ego,
443         void **ctx,
444         const char *name)
445 {
446   if (NULL == name) {
447     if (GNUNET_YES == init) {
448       init = GNUNET_NO;
449       start_get_attributes();
450     }
451     return;
452   }
453   if (0 != strcmp (name, ego_name))
454     return;
455   pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
456 }
457
458
459 static void
460 run (void *cls,
461      char *const *args,
462      const char *cfgfile,
463      const struct GNUNET_CONFIGURATION_Handle *c)
464 {
465   ret = 0;
466   if (NULL == ego_name)
467   {
468     ret = 1;
469     fprintf (stderr,
470              _("Ego is required\n"));
471     return;
472   }
473
474   if ( (NULL == attr_value) && (NULL != attr_name) )
475   {
476     ret = 1;
477     fprintf (stderr,
478              _("Attribute value missing!\n"));
479     return;
480   }
481
482   if ( (NULL == rp) && (NULL != issue_attrs) )
483   {
484     ret = 1;
485     fprintf (stderr,
486              _("Requesting party key is required!\n"));
487     return;
488   }
489
490   reclaim_handle = GNUNET_RECLAIM_connect (c);
491   //Get Ego
492   identity_handle = GNUNET_IDENTITY_connect (c,
493                                              &ego_cb,
494                                              NULL);
495
496
497 }
498
499
500 int
501 main(int argc, char *const argv[])
502 {
503   exp_interval = GNUNET_TIME_UNIT_HOURS;
504   struct GNUNET_GETOPT_CommandLineOption options[] = {
505
506     GNUNET_GETOPT_option_string ('a',
507                                  "add",
508                                  "NAME",
509                                  gettext_noop ("Add an attribute NAME"),
510                                  &attr_name),
511
512     GNUNET_GETOPT_option_string ('V',
513                                  "value",
514                                  "VALUE",
515                                  gettext_noop ("The attribute VALUE"),
516                                  &attr_value),
517     GNUNET_GETOPT_option_string ('e',
518                                  "ego",
519                                  "EGO",
520                                  gettext_noop ("The EGO to use"),
521                                  &ego_name),
522     GNUNET_GETOPT_option_string ('r',
523                                  "rp",
524                                  "RP",
525                                  gettext_noop ("Specify the relying party for issue"),
526                                  &rp),
527     GNUNET_GETOPT_option_flag ('D',
528                                "dump",
529                                gettext_noop ("List attributes for EGO"),
530                                &list),
531     GNUNET_GETOPT_option_string ('i',
532                                  "issue",
533                                  "A1,A2,...",
534                                  gettext_noop ("Issue a ticket for a set of attributes separated by comma"),
535                                  &issue_attrs),
536     GNUNET_GETOPT_option_string ('C',
537                                  "consume",
538                                  "TICKET",
539                                  gettext_noop ("Consume a ticket"),
540                                  &consume_ticket),
541     GNUNET_GETOPT_option_string ('R',
542                                  "revoke",
543                                  "TICKET",
544                                  gettext_noop ("Revoke a ticket"),
545                                  &revoke_ticket),
546     GNUNET_GETOPT_option_string ('t',
547                                  "type",
548                                  "TYPE",
549                                  gettext_noop ("Type of attribute"),
550                                  &type_str),
551     GNUNET_GETOPT_option_relative_time ('E',
552                                         "expiration",
553                                         "INTERVAL",
554                                         gettext_noop ("Expiration interval of the attribute"),
555                                         &exp_interval),
556
557     GNUNET_GETOPT_OPTION_END
558   };
559   if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "ct",
560                                        "ct", options,
561                                        &run, NULL))
562     return 1;
563   else
564     return ret;
565 }