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