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