Switch to $GNUNET_TMP in all configuration files.
[oweals/gnunet.git] / src / identity-provider / gnunet-idp.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
6    it under the terms of the GNU General Public License as published
7    by the Free Software Foundation; either version 3, or (at your
8    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    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with GNUnet; see the file COPYING.  If not, write to the
17    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18    Boston, MA 02110-1301, USA.
19    */
20 /**
21  * @author Martin Schanzenbach
22  * @file src/identity-provider/gnunet-idp.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_identity_provider_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  * IdP handle
91  */
92 static struct GNUNET_IDENTITY_PROVIDER_Handle *idp_handle;
93
94 /**
95  * IdP operation
96  */
97 static struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
98
99 /**
100  * Attribute iterator
101  */
102 static struct GNUNET_IDENTITY_PROVIDER_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_IDENTITY_PROVIDER_Ticket ticket;
123
124 /**
125  * Attribute list
126  */
127 static struct GNUNET_IDENTITY_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 static void
140 do_cleanup(void *cls)
141 {
142   if (NULL != timeout)
143     GNUNET_SCHEDULER_cancel (timeout);
144   if (NULL != idp_op)
145     GNUNET_IDENTITY_PROVIDER_cancel (idp_op);
146   if (NULL != attr_iterator)
147     GNUNET_IDENTITY_PROVIDER_get_attributes_stop (attr_iterator);
148   if (NULL != idp_handle)
149     GNUNET_IDENTITY_PROVIDER_disconnect (idp_handle);
150   if (NULL != identity_handle)
151     GNUNET_IDENTITY_disconnect (identity_handle);
152   if (NULL != abe_key)
153     GNUNET_free (abe_key);
154   if (NULL != attr_list)
155     GNUNET_free (attr_list);
156 }
157
158 static void
159 ticket_issue_cb (void* cls,
160                  const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
161 {
162   char* ticket_str;
163   idp_op = NULL;
164   if (NULL != ticket) {
165     ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
166                                                       sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
167     printf("%s\n",
168            ticket_str);
169     GNUNET_free (ticket_str);
170   }
171   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
172 }
173
174 static void
175 store_attr_cont (void *cls,
176                  int32_t success,
177                  const char*emsg)
178 {
179   idp_op = NULL;
180   if (GNUNET_SYSERR == success) {
181     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
182                 "%s\n", emsg);
183   }
184   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
185 }
186
187 static void
188 process_attrs (void *cls,
189          const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
190          const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
191 {
192   char *value_str;
193   if (NULL == identity)
194   {
195     idp_op = NULL;
196     GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
197     return;
198   }
199   if (NULL == attr)
200   {
201     ret = 1;
202     return;
203   }
204   value_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type,
205                                                      attr->data,
206                                                      attr->data_size);
207   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
208               "%s: %s\n", attr->name, value_str);
209 }
210
211
212 static void
213 iter_error (void *cls)
214 {
215   attr_iterator = NULL;
216   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
217               "Failed to iterate over attributes\n");
218   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
219 }
220
221 static void
222 timeout_task (void *cls)
223 {
224   timeout = NULL;
225   ret = 1;
226   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
227               "Timeout\n");
228   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
229 }
230
231 static void
232 process_rvk (void *cls, int success, const char* msg)
233 {
234   idp_op = NULL;
235   if (GNUNET_OK != success)
236   {
237     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
238                 "Revocation failed.\n");
239     ret = 1;
240   }
241   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
242 }
243
244 static void
245 iter_finished (void *cls)
246 {
247   struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
248   char *data;
249   size_t data_size;
250   int type;
251
252   attr_iterator = NULL;
253   if (list)
254   {
255     GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
256     return;
257   }
258
259   if (issue_attrs)
260   {
261     idp_op = GNUNET_IDENTITY_PROVIDER_ticket_issue (idp_handle,
262                                                     pkey,
263                                                     &rp_key,
264                                                     attr_list,
265                                                     &ticket_issue_cb,
266                                                     NULL);
267     return;
268   }
269   if (consume_ticket)
270   {
271     idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (idp_handle,
272                                                       pkey,
273                                                       &ticket,
274                                                       &process_attrs,
275                                                       NULL);
276     timeout = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10),
277                                             &timeout_task,
278                                             NULL);
279     return;
280   }
281   if (revoke_ticket)
282   {
283     idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (idp_handle,
284                                                      pkey,
285                                                      &ticket,
286                                                      &process_rvk,
287                                                      NULL);
288     return;
289   }
290   if (attr_name)
291   {
292     if (NULL == type_str)
293       type = GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING;
294     else
295       type = GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (type_str);
296
297     GNUNET_assert (GNUNET_SYSERR != GNUNET_IDENTITY_ATTRIBUTE_string_to_value (type,
298                                                                                attr_value,
299                                                                                (void**)&data,
300                                                                                &data_size));
301     claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr_name,
302                                                  type,
303                                                  data,
304                                                  data_size);
305     idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (idp_handle,
306                                                        pkey,
307                                                        claim,
308                                                        &exp_interval,
309                                                        &store_attr_cont,
310                                                        NULL);
311     return;
312   }
313   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
314 }
315
316 static void
317 iter_cb (void *cls,
318          const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
319          const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
320 {
321   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
322   char *attrs_tmp;
323   char *attr_str;
324
325   if (issue_attrs)
326   {
327     attrs_tmp = GNUNET_strdup (issue_attrs);
328     attr_str = strtok (attrs_tmp, ",");
329     while (NULL != attr_str) {
330       if (0 != strcmp (attr_str, attr->name)) {
331         attr_str = strtok (NULL, ",");
332         continue;
333       }
334       le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
335       le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr->name,
336                                                        attr->type,
337                                                        attr->data,
338                                                        attr->data_size);
339       GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
340                                    attr_list->list_tail,
341                                    le);
342       break;
343     }
344     GNUNET_free (attrs_tmp);
345   } else if (list) {
346     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
347                 "%s: %s\n", attr->name, (char*)attr->data);
348   }
349   GNUNET_IDENTITY_PROVIDER_get_attributes_next (attr_iterator);
350 }
351
352 static void
353 ego_iter_finished (void *cls)
354 {
355   if (NULL == pkey)
356   {
357     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
358                 "Ego %s not found\n", ego_name);
359     return;
360   }
361
362   if (NULL != rp)
363     GNUNET_CRYPTO_ecdsa_public_key_from_string (rp,
364                                                 strlen (rp),
365                                                 &rp_key);
366   if (NULL != consume_ticket)
367     GNUNET_STRINGS_string_to_data (consume_ticket,
368                                    strlen (consume_ticket),
369                                    &ticket,
370                                    sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
371   if (NULL != revoke_ticket)
372     GNUNET_STRINGS_string_to_data (revoke_ticket,
373                                    strlen (revoke_ticket),
374                                    &ticket,
375                                    sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
376
377
378   attr_list = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
379
380   attr_iterator = GNUNET_IDENTITY_PROVIDER_get_attributes_start (idp_handle,
381                                                                  pkey,
382                                                                  &iter_error,
383                                                                  NULL,
384                                                                  &iter_cb,
385                                                                  NULL,
386                                                                  &iter_finished,
387                                                                  NULL);
388
389
390 }
391
392 static int init = GNUNET_YES;
393
394 static void
395 ego_cb (void *cls,
396         struct GNUNET_IDENTITY_Ego *ego,
397         void **ctx,
398         const char *name)
399 {
400   if (NULL == name) {
401     if (GNUNET_YES == init) {
402       init = GNUNET_NO;
403       GNUNET_SCHEDULER_add_now (&ego_iter_finished, NULL);
404     }
405     return;
406   }
407   if (0 != strcmp (name, ego_name))
408     return;
409   pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
410 }
411
412
413 static void
414 run (void *cls,
415      char *const *args,
416      const char *cfgfile,
417      const struct GNUNET_CONFIGURATION_Handle *c)
418 {
419   ret = 0;
420   if (NULL == ego_name)
421   {
422     ret = 1;
423     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
424                 _("Ego is required\n"));
425     return;
426   }
427
428   if ( (NULL == attr_value) && (NULL != attr_name) )
429   {
430     ret = 1;
431     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
432                 _("Attribute value missing!\n"));
433     return;
434   }
435
436   if ( (NULL == rp) && (NULL != issue_attrs) )
437   {
438     ret = 1;
439     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
440                 _("Requesting party key is required!\n"));
441     return;
442   }
443
444   idp_handle = GNUNET_IDENTITY_PROVIDER_connect (c);
445   //Get Ego
446   identity_handle = GNUNET_IDENTITY_connect (c,
447                                              &ego_cb,
448                                              NULL);
449
450
451 }
452
453
454 int
455 main(int argc, char *const argv[])
456 {
457   exp_interval = GNUNET_TIME_UNIT_HOURS;
458   struct GNUNET_GETOPT_CommandLineOption options[] = {
459
460     GNUNET_GETOPT_option_string ('a',
461                                  "add",
462                                  NULL,
463                                  gettext_noop ("Add attribute"),
464                                  &attr_name),
465
466     GNUNET_GETOPT_option_string ('V',
467                                  "value",
468                                  NULL,
469                                  gettext_noop ("Attribute value"),
470                                  &attr_value),
471     GNUNET_GETOPT_option_string ('e',
472                                  "ego",
473                                  NULL,
474                                  gettext_noop ("Ego"),
475                                  &ego_name),
476     GNUNET_GETOPT_option_string ('r',
477                                  "rp",
478                                  NULL,
479                                  gettext_noop ("Audience (relying party)"),
480                                  &rp),
481     GNUNET_GETOPT_option_flag ('D',
482                                "dump",
483                                gettext_noop ("List attributes for Ego"),
484                                &list),
485     GNUNET_GETOPT_option_string ('i',
486                                  "issue",
487                                  NULL,
488                                  gettext_noop ("Issue a ticket"),
489                                  &issue_attrs),
490     GNUNET_GETOPT_option_string ('C',
491                                  "consume",
492                                  NULL,
493                                  gettext_noop ("Consume a ticket"),
494                                  &consume_ticket),
495     GNUNET_GETOPT_option_string ('R',
496                                  "revoke",
497                                  NULL,
498                                  gettext_noop ("Revoke a ticket"),
499                                  &revoke_ticket),
500     GNUNET_GETOPT_option_string ('t',
501                                  "type",
502                                  NULL,
503                                  gettext_noop ("Type of attribute"),
504                                  &type_str),
505     GNUNET_GETOPT_option_relative_time ('E',
506                                         "expiration",
507                                         NULL,
508                                         gettext_noop ("Expiration interval of the attribute"),
509                                         &exp_interval),
510
511     GNUNET_GETOPT_OPTION_END
512   };
513   if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "ct",
514                                        "ct", options,
515                                        &run, NULL))
516     return 1;
517   else
518     return ret;
519 }