Merge branch 'master' of git+ssh://gnunet.org/gnunet
[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 static void
135 do_cleanup(void *cls)
136 {
137   if (NULL != attr_iterator)
138     GNUNET_IDENTITY_PROVIDER_get_attributes_stop (attr_iterator);
139   if (NULL != idp_handle)
140     GNUNET_IDENTITY_PROVIDER_disconnect (idp_handle);
141   if (NULL != identity_handle)
142     GNUNET_IDENTITY_disconnect (identity_handle);
143   if (NULL != abe_key)
144     GNUNET_free (abe_key);
145   if (NULL != attr_list)
146     GNUNET_free (attr_list);
147 }
148
149 static void
150 ticket_issue_cb (void* cls,
151                  const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
152 {
153   char* ticket_str;
154   if (NULL != ticket) {
155     ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
156                                                       sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
157     printf("%s\n",
158            ticket_str);
159     GNUNET_free (ticket_str);
160   }
161   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
162 }
163
164 static void
165 store_attr_cont (void *cls,
166                  int32_t success,
167                  const char*emsg)
168 {
169   if (GNUNET_SYSERR == success) {
170     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
171                 "%s\n", emsg);
172   }
173   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
174 }
175
176 static void
177 process_attrs (void *cls,
178          const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
179          const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
180 {
181   char *value_str;
182   if (NULL == identity)
183   {
184     GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
185     return;
186   }
187   if (NULL == attr)
188   {
189     ret = 1;
190     return;
191   }
192   value_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type,
193                                                      attr->data,
194                                                      attr->data_size);
195   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
196               "%s: %s\n", attr->name, value_str);
197 }
198
199
200 static void
201 iter_error (void *cls)
202 {
203   attr_iterator = NULL;
204   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
205               "Failed to iterate over attributes\n");
206   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
207 }
208
209 static void
210 process_rvk (void *cls, int success, const char* msg)
211 {
212   if (GNUNET_OK != success)
213   {
214     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
215                 "Revocation failed.\n");
216     ret = 1;
217   }
218   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
219 }
220
221 static void
222 iter_finished (void *cls)
223 {
224   struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
225   char *data;
226   size_t data_size;
227   int type;
228
229   attr_iterator = NULL;
230   if (list)
231   {
232     GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
233     return;
234   }
235
236   if (issue_attrs)
237   {
238     idp_op = GNUNET_IDENTITY_PROVIDER_ticket_issue (idp_handle,
239                                                     pkey,
240                                                     &rp_key,
241                                                     attr_list,
242                                                     &ticket_issue_cb,
243                                                     NULL);
244     return;
245   }
246   if (consume_ticket)
247   {
248     idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (idp_handle,
249                                                       pkey,
250                                                       &ticket,
251                                                       &process_attrs,
252                                                       NULL);
253     return;
254   }
255   if (revoke_ticket)
256   {
257     idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (idp_handle,
258                                                      pkey,
259                                                      &ticket,
260                                                      &process_rvk,
261                                                      NULL);
262     return;
263   }
264   if (NULL == type_str)
265     type = GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING;
266   else
267     type = GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (type_str);
268
269   GNUNET_assert (GNUNET_SYSERR != GNUNET_IDENTITY_ATTRIBUTE_string_to_value (type,
270                                              attr_value,
271                                              (void**)&data,
272                                              &data_size));
273   claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr_name,
274                                                type,
275                                                data,
276                                                data_size);
277   idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (idp_handle,
278                                                      pkey,
279                                                      claim,
280                                                      &exp_interval,
281                                                      &store_attr_cont,
282                                                      NULL);
283
284
285 }
286
287 static void
288 iter_cb (void *cls,
289          const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
290          const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
291 {
292   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
293   char *attrs_tmp;
294   char *attr_str;
295
296   if (issue_attrs)
297   {
298     attrs_tmp = GNUNET_strdup (issue_attrs);
299     attr_str = strtok (attrs_tmp, ",");
300     while (NULL != attr_str) {
301       if (0 != strcmp (attr_str, attr->name)) {
302         attr_str = strtok (NULL, ",");
303         continue;
304       }
305       le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
306       le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr->name,
307                                                        attr->type,
308                                                        attr->data,
309                                                        attr->data_size);
310       GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
311                                    attr_list->list_tail,
312                                    le);
313       break;
314     }
315     GNUNET_free (attrs_tmp);
316   } else if (list) {
317     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
318                 "%s: %s\n", attr->name, (char*)attr->data);
319   }
320   GNUNET_IDENTITY_PROVIDER_get_attributes_next (attr_iterator);
321 }
322
323 static void
324 ego_cb (void *cls,
325         struct GNUNET_IDENTITY_Ego *ego,
326         void **ctx,
327         const char *name)
328 {
329   if (NULL == name)
330     return;
331   if (0 != strcmp (name, ego_name))
332     return;
333   pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
334
335   if (NULL != rp)
336     GNUNET_CRYPTO_ecdsa_public_key_from_string (rp,
337                                                 strlen (rp),
338                                                 &rp_key);
339   if (NULL != consume_ticket)
340     GNUNET_STRINGS_string_to_data (consume_ticket,
341                                    strlen (consume_ticket),
342                                    &ticket,
343                                    sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
344   if (NULL != revoke_ticket)
345     GNUNET_STRINGS_string_to_data (revoke_ticket,
346                                    strlen (revoke_ticket),
347                                    &ticket,
348                                    sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
349
350
351   attr_list = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
352
353   attr_iterator = GNUNET_IDENTITY_PROVIDER_get_attributes_start (idp_handle,
354                                                                  pkey,
355                                                                  &iter_error,
356                                                                  NULL,
357                                                                  &iter_cb,
358                                                                  NULL,
359                                                                  &iter_finished,
360                                                                  NULL);
361
362
363 }
364
365 static void
366 run (void *cls,
367      char *const *args,
368      const char *cfgfile,
369      const struct GNUNET_CONFIGURATION_Handle *c)
370 {
371   ret = 0;
372   if (NULL == ego_name)
373   {
374     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
375                 _("Ego is required\n"));
376     return;
377   } 
378
379   idp_handle = GNUNET_IDENTITY_PROVIDER_connect (c);
380   //Get Ego
381   identity_handle = GNUNET_IDENTITY_connect (c,
382                                              &ego_cb,
383                                              NULL);
384
385
386 }
387
388
389 int
390 main(int argc, char *const argv[])
391 {
392   exp_interval = GNUNET_TIME_UNIT_HOURS;
393   struct GNUNET_GETOPT_CommandLineOption options[] = {
394
395     GNUNET_GETOPT_option_string ('a',
396                                  "add",
397                                  NULL,
398                                  gettext_noop ("Add attribute"),
399                                  &attr_name),
400
401     GNUNET_GETOPT_option_string ('V',
402                                  "value",
403                                  NULL,
404                                  gettext_noop ("Attribute value"),
405                                  &attr_value),
406     GNUNET_GETOPT_option_string ('e',
407                                  "ego",
408                                  NULL,
409                                  gettext_noop ("Ego"),
410                                  &ego_name),
411     GNUNET_GETOPT_option_string ('r',
412                                  "rp",
413                                  NULL,
414                                  gettext_noop ("Audience (relying party)"),
415                                  &rp),
416     GNUNET_GETOPT_option_flag ('D',
417                                "dump",
418                                gettext_noop ("List attributes for Ego"),
419                                &list),
420     GNUNET_GETOPT_option_string ('i',
421                                  "issue",
422                                  NULL,
423                                  gettext_noop ("Issue a ticket"),
424                                  &issue_attrs),
425     GNUNET_GETOPT_option_string ('C',
426                                  "consume",
427                                  NULL,
428                                  gettext_noop ("Consume a ticket"),
429                                  &consume_ticket),
430     GNUNET_GETOPT_option_string ('R',
431                                  "revoke",
432                                  NULL,
433                                  gettext_noop ("Revoke a ticket"),
434                                  &revoke_ticket),
435     GNUNET_GETOPT_option_string ('t',
436                                  "type",
437                                  NULL,
438                                  gettext_noop ("Type of attribute"),
439                                  &type_str),
440     GNUNET_GETOPT_option_relative_time ('E',
441                                         "expiration",
442                                         NULL,
443                                         gettext_noop ("Expiration interval of the attribute"),
444                                         &exp_interval),
445
446     GNUNET_GETOPT_OPTION_END
447   };
448   if (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "ct",
449                       "ct", options,
450                       &run, NULL))
451     return 0;
452   else
453     return 1;
454 }