issue case insensitivity
[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 static void
143 do_cleanup(void *cls)
144 {
145   cleanup_task = NULL;
146   if (NULL != timeout)
147     GNUNET_SCHEDULER_cancel (timeout);
148   if (NULL != reclaim_op)
149     GNUNET_RECLAIM_cancel (reclaim_op);
150   if (NULL != attr_iterator)
151     GNUNET_RECLAIM_get_attributes_stop (attr_iterator);
152   if (NULL != reclaim_handle)
153     GNUNET_RECLAIM_disconnect (reclaim_handle);
154   if (NULL != identity_handle)
155     GNUNET_IDENTITY_disconnect (identity_handle);
156   if (NULL != abe_key)
157     GNUNET_free (abe_key);
158   if (NULL != attr_list)
159     GNUNET_free (attr_list);
160 }
161
162 static void
163 ticket_issue_cb (void* cls,
164                  const struct GNUNET_RECLAIM_Ticket *ticket)
165 {
166   char* ticket_str;
167   reclaim_op = NULL;
168   if (NULL != ticket) {
169     ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
170                                                       sizeof (struct GNUNET_RECLAIM_Ticket));
171     printf("%s\n",
172            ticket_str);
173     GNUNET_free (ticket_str);
174   }
175   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
176 }
177
178 static void
179 store_attr_cont (void *cls,
180                  int32_t success,
181                  const char*emsg)
182 {
183   reclaim_op = NULL;
184   if (GNUNET_SYSERR == success) {
185     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
186                 "%s\n", emsg);
187   }
188   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
189 }
190
191 static void
192 process_attrs (void *cls,
193          const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
194          const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
195 {
196   char *value_str;
197   if (NULL == identity)
198   {
199     reclaim_op = NULL;
200     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
201     return;
202   }
203   if (NULL == attr)
204   {
205     ret = 1;
206     return;
207   }
208   value_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
209                                                         attr->data,
210                                                         attr->data_size);
211   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
212               "%s: %s\n", attr->name, value_str);
213 }
214
215
216 static void
217 iter_error (void *cls)
218 {
219   attr_iterator = NULL;
220   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
221               "Failed to iterate over attributes\n");
222   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
223 }
224
225 static void
226 timeout_task (void *cls)
227 {
228   timeout = NULL;
229   ret = 1;
230   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
231               "Timeout\n");
232   if (NULL == cleanup_task)
233     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
234 }
235
236 static void
237 process_rvk (void *cls, int success, const char* msg)
238 {
239   reclaim_op = NULL;
240   if (GNUNET_OK != success)
241   {
242     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
243                 "Revocation failed.\n");
244     ret = 1;
245   }
246   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
247 }
248
249 static void
250 iter_finished (void *cls)
251 {
252   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
253   char *data;
254   size_t data_size;
255   int type;
256
257   attr_iterator = NULL;
258   if (list)
259   {
260     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
261     return;
262   }
263
264   if (issue_attrs)
265   {
266     reclaim_op = GNUNET_RECLAIM_ticket_issue (reclaim_handle,
267                                               pkey,
268                                               &rp_key,
269                                               attr_list,
270                                               &ticket_issue_cb,
271                                               NULL);
272     return;
273   }
274   if (consume_ticket)
275   {
276     reclaim_op = GNUNET_RECLAIM_ticket_consume (reclaim_handle,
277                                                 pkey,
278                                                 &ticket,
279                                                 &process_attrs,
280                                                 NULL);
281     timeout = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10),
282                                             &timeout_task,
283                                             NULL);
284     return;
285   }
286   if (revoke_ticket)
287   {
288     reclaim_op = GNUNET_RECLAIM_ticket_revoke (reclaim_handle,
289                                                pkey,
290                                                &ticket,
291                                                &process_rvk,
292                                                NULL);
293     return;
294   }
295   if (attr_name)
296   {
297     if (NULL == type_str)
298       type = GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING;
299     else
300       type = GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (type_str);
301
302     GNUNET_assert (GNUNET_SYSERR != GNUNET_RECLAIM_ATTRIBUTE_string_to_value (type,
303                                                                               attr_value,
304                                                                               (void**)&data,
305                                                                               &data_size));
306     claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name,
307                                                  type,
308                                                  data,
309                                                  data_size);
310     reclaim_op = GNUNET_RECLAIM_attribute_store (reclaim_handle,
311                                                  pkey,
312                                                  claim,
313                                                  &exp_interval,
314                                                  &store_attr_cont,
315                                                  NULL);
316     return;
317   }
318   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
319 }
320
321 static void
322 iter_cb (void *cls,
323          const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
324          const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
325 {
326   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
327   char *attrs_tmp;
328   char *attr_str;
329
330   if (issue_attrs)
331   {
332     attrs_tmp = GNUNET_strdup (issue_attrs);
333     attr_str = strtok (attrs_tmp, ",");
334     while (NULL != attr_str) {
335       if (0 != strcasecmp (attr_str, attr->name)) {
336         attr_str = strtok (NULL, ",");
337         continue;
338       }
339       le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
340       le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name,
341                                                       attr->type,
342                                                       attr->data,
343                                                       attr->data_size);
344       GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
345                                    attr_list->list_tail,
346                                    le);
347       break;
348     }
349     GNUNET_free (attrs_tmp);
350   } else if (list) {
351     attr_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
352                                                          attr->data,
353                                                          attr->data_size);
354     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
355                 "%s: %s\n", attr->name, attr_str);
356   }
357   GNUNET_RECLAIM_get_attributes_next (attr_iterator);
358 }
359
360 static void
361 start_get_attributes ()
362 {
363   if (NULL == pkey)
364   {
365     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
366                 "Ego %s not found\n", ego_name);
367     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
368     return;
369   }
370
371   if (NULL != rp)
372     GNUNET_CRYPTO_ecdsa_public_key_from_string (rp,
373                                                 strlen (rp),
374                                                 &rp_key);
375   if (NULL != consume_ticket)
376     GNUNET_STRINGS_string_to_data (consume_ticket,
377                                    strlen (consume_ticket),
378                                    &ticket,
379                                    sizeof (struct GNUNET_RECLAIM_Ticket));
380   if (NULL != revoke_ticket)
381     GNUNET_STRINGS_string_to_data (revoke_ticket,
382                                    strlen (revoke_ticket),
383                                    &ticket,
384                                    sizeof (struct GNUNET_RECLAIM_Ticket));
385
386
387   attr_list = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
388
389   attr_iterator = GNUNET_RECLAIM_get_attributes_start (reclaim_handle,
390                                                        pkey,
391                                                        &iter_error,
392                                                        NULL,
393                                                        &iter_cb,
394                                                        NULL,
395                                                        &iter_finished,
396                                                        NULL);
397
398
399 }
400
401 static int init = GNUNET_YES;
402
403 static void
404 ego_cb (void *cls,
405         struct GNUNET_IDENTITY_Ego *ego,
406         void **ctx,
407         const char *name)
408 {
409   if (NULL == name) {
410     if (GNUNET_YES == init) {
411       init = GNUNET_NO;
412       start_get_attributes();
413     }
414     return;
415   }
416   if (0 != strcmp (name, ego_name))
417     return;
418   pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
419 }
420
421
422 static void
423 run (void *cls,
424      char *const *args,
425      const char *cfgfile,
426      const struct GNUNET_CONFIGURATION_Handle *c)
427 {
428   ret = 0;
429   if (NULL == ego_name)
430   {
431     ret = 1;
432     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
433                 _("Ego is required\n"));
434     return;
435   }
436
437   if ( (NULL == attr_value) && (NULL != attr_name) )
438   {
439     ret = 1;
440     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
441                 _("Attribute value missing!\n"));
442     return;
443   }
444
445   if ( (NULL == rp) && (NULL != issue_attrs) )
446   {
447     ret = 1;
448     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
449                 _("Requesting party key is required!\n"));
450     return;
451   }
452
453   reclaim_handle = GNUNET_RECLAIM_connect (c);
454   //Get Ego
455   identity_handle = GNUNET_IDENTITY_connect (c,
456                                              &ego_cb,
457                                              NULL);
458
459
460 }
461
462
463 int
464 main(int argc, char *const argv[])
465 {
466   exp_interval = GNUNET_TIME_UNIT_HOURS;
467   struct GNUNET_GETOPT_CommandLineOption options[] = {
468
469     GNUNET_GETOPT_option_string ('a',
470                                  "add",
471                                  NULL,
472                                  gettext_noop ("Add attribute"),
473                                  &attr_name),
474
475     GNUNET_GETOPT_option_string ('V',
476                                  "value",
477                                  NULL,
478                                  gettext_noop ("Attribute value"),
479                                  &attr_value),
480     GNUNET_GETOPT_option_string ('e',
481                                  "ego",
482                                  NULL,
483                                  gettext_noop ("Ego"),
484                                  &ego_name),
485     GNUNET_GETOPT_option_string ('r',
486                                  "rp",
487                                  NULL,
488                                  gettext_noop ("Audience (relying party)"),
489                                  &rp),
490     GNUNET_GETOPT_option_flag ('D',
491                                "dump",
492                                gettext_noop ("List attributes for Ego"),
493                                &list),
494     GNUNET_GETOPT_option_string ('i',
495                                  "issue",
496                                  NULL,
497                                  gettext_noop ("Issue a ticket"),
498                                  &issue_attrs),
499     GNUNET_GETOPT_option_string ('C',
500                                  "consume",
501                                  NULL,
502                                  gettext_noop ("Consume a ticket"),
503                                  &consume_ticket),
504     GNUNET_GETOPT_option_string ('R',
505                                  "revoke",
506                                  NULL,
507                                  gettext_noop ("Revoke a ticket"),
508                                  &revoke_ticket),
509     GNUNET_GETOPT_option_string ('t',
510                                  "type",
511                                  NULL,
512                                  gettext_noop ("Type of attribute"),
513                                  &type_str),
514     GNUNET_GETOPT_option_relative_time ('E',
515                                         "expiration",
516                                         NULL,
517                                         gettext_noop ("Expiration interval of the attribute"),
518                                         &exp_interval),
519
520     GNUNET_GETOPT_OPTION_END
521   };
522   if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "ct",
523                                        "ct", options,
524                                        &run, NULL))
525     return 1;
526   else
527     return ret;
528 }