Merge branch 'license/spdx'
[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]\n", attr->name, value_str, attr_type, attr->version);
223 }
224
225
226 static void
227 iter_error (void *cls)
228 {
229   attr_iterator = NULL;
230   fprintf (stderr,
231            "Failed to iterate over attributes\n");
232   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
233 }
234
235 static void
236 timeout_task (void *cls)
237 {
238   timeout = NULL;
239   ret = 1;
240   fprintf (stderr,
241            "Timeout\n");
242   if (NULL == cleanup_task)
243     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
244 }
245
246 static void
247 process_rvk (void *cls, int success, const char* msg)
248 {
249   reclaim_op = NULL;
250   if (GNUNET_OK != success)
251   {
252     fprintf (stderr,
253              "Revocation failed.\n");
254     ret = 1;
255   }
256   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
257 }
258
259 static void
260 iter_finished (void *cls)
261 {
262   char *data;
263   size_t data_size;
264   int type;
265
266   attr_iterator = NULL;
267   if (list)
268   {
269     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
270     return;
271   }
272
273   if (issue_attrs)
274   {
275     reclaim_op = GNUNET_RECLAIM_ticket_issue (reclaim_handle,
276                                               pkey,
277                                               &rp_key,
278                                               attr_list,
279                                               &ticket_issue_cb,
280                                               NULL);
281     return;
282   }
283   if (consume_ticket)
284   {
285     reclaim_op = GNUNET_RECLAIM_ticket_consume (reclaim_handle,
286                                                 pkey,
287                                                 &ticket,
288                                                 &process_attrs,
289                                                 NULL);
290     timeout = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10),
291                                             &timeout_task,
292                                             NULL);
293     return;
294   }
295   if (revoke_ticket)
296   {
297     reclaim_op = GNUNET_RECLAIM_ticket_revoke (reclaim_handle,
298                                                pkey,
299                                                &ticket,
300                                                &process_rvk,
301                                                NULL);
302     return;
303   }
304   if (attr_name)
305   {
306     if (NULL == type_str)
307       type = GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING;
308     else
309       type = GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (type_str);
310
311     GNUNET_assert (GNUNET_SYSERR != GNUNET_RECLAIM_ATTRIBUTE_string_to_value (type,
312                                                                               attr_value,
313                                                                               (void**)&data,
314                                                                               &data_size));
315     if (NULL != claim)
316     {
317       claim->type = type;
318       claim->data = data;
319       claim->data_size = data_size;
320     }
321     else
322     {
323       claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name,
324                                                   type,
325                                                   data,
326                                                   data_size);
327     }
328     reclaim_op = GNUNET_RECLAIM_attribute_store (reclaim_handle,
329                                                  pkey,
330                                                  claim,
331                                                  &exp_interval,
332                                                  &store_attr_cont,
333                                                  NULL);
334     GNUNET_free (data);
335     GNUNET_free (claim);
336     return;
337   }
338   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
339 }
340
341 static void
342 iter_cb (void *cls,
343          const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
344          const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
345 {
346   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
347   char *attrs_tmp;
348   char *attr_str;
349   const char *attr_type;
350
351   if ((NULL != attr_name) && (NULL != claim))
352   {
353     if (0 == strcasecmp (attr_name, attr->name))
354     {
355       claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name,
356                                                             attr->type,
357                                                             attr->data,
358                                                             attr->data_size);
359     }
360   }
361   else if (issue_attrs)
362   {
363     attrs_tmp = GNUNET_strdup (issue_attrs);
364     attr_str = strtok (attrs_tmp, ",");
365     while (NULL != attr_str) {
366       if (0 != strcasecmp (attr_str, attr->name)) {
367         attr_str = strtok (NULL, ",");
368         continue;
369       }
370       le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
371       le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name,
372                                                       attr->type,
373                                                       attr->data,
374                                                       attr->data_size);
375       le->claim->version = attr->version;
376       GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
377                                    attr_list->list_tail,
378                                    le);
379       break;
380     }
381     GNUNET_free (attrs_tmp);
382   } 
383   else if (list)
384   {
385     attr_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
386                                                          attr->data,
387                                                          attr->data_size);
388     attr_type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr->type);
389     fprintf (stdout,
390              "%s: %s [%s,v%u]\n", attr->name, attr_str, attr_type, attr->version);
391   }
392   GNUNET_RECLAIM_get_attributes_next (attr_iterator);
393 }
394
395 static void
396 start_get_attributes ()
397 {
398   if (NULL == pkey)
399   {
400     fprintf (stderr,
401              "Ego %s not found\n", ego_name);
402     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
403     return;
404   }
405
406   if (NULL != rp)
407     GNUNET_CRYPTO_ecdsa_public_key_from_string (rp,
408                                                 strlen (rp),
409                                                 &rp_key);
410   if (NULL != consume_ticket)
411     GNUNET_STRINGS_string_to_data (consume_ticket,
412                                    strlen (consume_ticket),
413                                    &ticket,
414                                    sizeof (struct GNUNET_RECLAIM_Ticket));
415   if (NULL != revoke_ticket)
416     GNUNET_STRINGS_string_to_data (revoke_ticket,
417                                    strlen (revoke_ticket),
418                                    &ticket,
419                                    sizeof (struct GNUNET_RECLAIM_Ticket));
420
421   attr_list = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
422   claim = NULL;
423   attr_iterator = GNUNET_RECLAIM_get_attributes_start (reclaim_handle,
424                                                        pkey,
425                                                        &iter_error,
426                                                        NULL,
427                                                        &iter_cb,
428                                                        NULL,
429                                                        &iter_finished,
430                                                        NULL);
431
432
433 }
434
435 static int init = GNUNET_YES;
436
437 static void
438 ego_cb (void *cls,
439         struct GNUNET_IDENTITY_Ego *ego,
440         void **ctx,
441         const char *name)
442 {
443   if (NULL == name) {
444     if (GNUNET_YES == init) {
445       init = GNUNET_NO;
446       start_get_attributes();
447     }
448     return;
449   }
450   if (0 != strcmp (name, ego_name))
451     return;
452   pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
453 }
454
455
456 static void
457 run (void *cls,
458      char *const *args,
459      const char *cfgfile,
460      const struct GNUNET_CONFIGURATION_Handle *c)
461 {
462   ret = 0;
463   if (NULL == ego_name)
464   {
465     ret = 1;
466     fprintf (stderr,
467              _("Ego is required\n"));
468     return;
469   }
470
471   if ( (NULL == attr_value) && (NULL != attr_name) )
472   {
473     ret = 1;
474     fprintf (stderr,
475              _("Attribute value missing!\n"));
476     return;
477   }
478
479   if ( (NULL == rp) && (NULL != issue_attrs) )
480   {
481     ret = 1;
482     fprintf (stderr,
483              _("Requesting party key is required!\n"));
484     return;
485   }
486
487   reclaim_handle = GNUNET_RECLAIM_connect (c);
488   //Get Ego
489   identity_handle = GNUNET_IDENTITY_connect (c,
490                                              &ego_cb,
491                                              NULL);
492
493
494 }
495
496
497 int
498 main(int argc, char *const argv[])
499 {
500   exp_interval = GNUNET_TIME_UNIT_HOURS;
501   struct GNUNET_GETOPT_CommandLineOption options[] = {
502
503     GNUNET_GETOPT_option_string ('a',
504                                  "add",
505                                  NULL,
506                                  gettext_noop ("Add attribute"),
507                                  &attr_name),
508
509     GNUNET_GETOPT_option_string ('V',
510                                  "value",
511                                  NULL,
512                                  gettext_noop ("Attribute value"),
513                                  &attr_value),
514     GNUNET_GETOPT_option_string ('e',
515                                  "ego",
516                                  NULL,
517                                  gettext_noop ("Ego"),
518                                  &ego_name),
519     GNUNET_GETOPT_option_string ('r',
520                                  "rp",
521                                  NULL,
522                                  gettext_noop ("Audience (relying party)"),
523                                  &rp),
524     GNUNET_GETOPT_option_flag ('D',
525                                "dump",
526                                gettext_noop ("List attributes for Ego"),
527                                &list),
528     GNUNET_GETOPT_option_string ('i',
529                                  "issue",
530                                  NULL,
531                                  gettext_noop ("Issue a ticket"),
532                                  &issue_attrs),
533     GNUNET_GETOPT_option_string ('C',
534                                  "consume",
535                                  NULL,
536                                  gettext_noop ("Consume a ticket"),
537                                  &consume_ticket),
538     GNUNET_GETOPT_option_string ('R',
539                                  "revoke",
540                                  NULL,
541                                  gettext_noop ("Revoke a ticket"),
542                                  &revoke_ticket),
543     GNUNET_GETOPT_option_string ('t',
544                                  "type",
545                                  NULL,
546                                  gettext_noop ("Type of attribute"),
547                                  &type_str),
548     GNUNET_GETOPT_option_relative_time ('E',
549                                         "expiration",
550                                         NULL,
551                                         gettext_noop ("Expiration interval of the attribute"),
552                                         &exp_interval),
553
554     GNUNET_GETOPT_OPTION_END
555   };
556   if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "ct",
557                                        "ct", options,
558                                        &run, NULL))
559     return 1;
560   else
561     return ret;
562 }