Merge branch 'abe' into identity_abe
[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_service.h"
31 #include "gnunet_signatures.h"
32
33 /**
34  * Init flag
35  */
36 static int init;
37
38 /**
39  * List attribute flag
40  */
41 static int list;
42
43 /**
44  * The attribute
45  */
46 static char* attr_name;
47
48 /**
49  * Attribute value
50  */
51 static char* attr_value;
52
53 /**
54  * Ego name
55  */
56 static char* ego_name;
57
58 /**
59  * Identity handle
60  */
61 static struct GNUNET_IDENTITY_Handle *identity_handle;
62
63 /**
64  * Namestore handle
65  */
66 static struct GNUNET_NAMESTORE_Handle *namestore_handle;
67
68 /**
69  * Namestore iterator
70  */
71 static struct GNUNET_NAMESTORE_ZoneIterator *ns_iterator;
72
73 /**
74  * Namestore queue
75  */
76 static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
77
78 /**
79  * Master ABE key
80  */
81 static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
82
83 static void
84 do_cleanup(void *cls)
85 {
86   if (NULL != ns_qe)
87     GNUNET_NAMESTORE_cancel (ns_qe);
88   if (NULL != ns_iterator)
89     GNUNET_NAMESTORE_zone_iteration_stop (ns_iterator);
90   if (NULL != namestore_handle)
91     GNUNET_NAMESTORE_disconnect (namestore_handle);
92   if (NULL != identity_handle)
93     GNUNET_IDENTITY_disconnect (identity_handle);
94   if (NULL != abe_key)
95     GNUNET_free (abe_key);
96 }
97
98 static void
99 ns_error_cb (void *cls)
100 {
101   ns_qe = NULL;
102   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
103               "Failed.");
104   do_cleanup(NULL);
105   return;
106 }
107
108 static void
109 store_attr_cont (void *cls,
110                  int32_t success,
111                  const char*emsg)
112 {
113   ns_qe = NULL;
114   if (GNUNET_SYSERR == success) {
115     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
116                 "%s\n", emsg);
117   } else {
118     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
119                 "Sucessfully added identity attribute %s=%s\n",
120                 attr_name, attr_value);
121   }
122   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
123 }
124
125 static void
126 store_abe_cont (void *cls,
127                  int32_t success,
128                  const char*emsg)
129 {
130   ns_qe = NULL;
131   if (GNUNET_SYSERR == success) {
132     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
133                 "%s\n", emsg);
134   } else {
135     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
136                 "Bootstrapped ABE master key. Please run command again.\n");
137   }
138   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
139 }
140
141 static void
142 iter_error (void *cls)
143 {
144   ns_iterator = NULL;
145   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
146               "Failed to iterate over attributes\n");
147   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
148 }
149
150 static void
151 iter_finished (void *cls)
152 {
153   ns_iterator = NULL;
154   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
155 }
156
157 static void
158 iter_cb (void *cls,
159             const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
160             const char *label,
161             unsigned int rd_count,
162             const struct GNUNET_GNSRECORD_Data *rd)
163 {
164   struct GNUNET_CRYPTO_AbeKey *key;
165   int i;
166   char *attr_value;
167   char* attrs[2];
168   for (i=0;i<rd_count;i++) {
169     if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd[i].record_type)
170       continue;
171     attrs[0] = (char*)label;
172     attrs[1] = 0;
173     key = GNUNET_CRYPTO_cpabe_create_key (abe_key,
174                                           attrs);
175     GNUNET_CRYPTO_cpabe_decrypt (rd[i].data,
176                                  rd[i].data_size,
177                                  key,
178                                  (void**)&attr_value);
179     GNUNET_CRYPTO_cpabe_delete_key (key);
180     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
181                 "%s: %s\n", label, attr_value);
182   }
183   GNUNET_NAMESTORE_zone_iterator_next (ns_iterator);
184 }
185
186 static void
187 abe_lookup_cb (void *cls,
188                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
189                const char *label,
190                unsigned int rd_count,
191                const struct GNUNET_GNSRECORD_Data *rd)
192 {
193   struct GNUNET_GNSRECORD_Data new_record;
194   struct GNUNET_CRYPTO_AbeMasterKey *new_key;
195   int i;
196   ssize_t size;
197   ns_qe = NULL;
198   for (i=0;i<rd_count;i++) {
199     if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
200       continue;
201     abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key (rd[i].data,
202                                                           rd[i].data_size);
203   }
204   if (NULL == abe_key) {
205     new_key = GNUNET_CRYPTO_cpabe_create_master_key ();
206     size = GNUNET_CRYPTO_cpabe_serialize_master_key (new_key,
207                                                      (void**)&new_record.data);
208     new_record.data_size = size;
209     new_record.record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
210     new_record.expiration_time = GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us;
211     new_record.flags = GNUNET_GNSRECORD_RF_PRIVATE;
212     ns_qe = GNUNET_NAMESTORE_records_store (namestore_handle,
213                                             zone,
214                                             "+",
215                                             1,
216                                             &new_record,
217                                             &store_abe_cont,
218                                             NULL);
219     return;
220   }
221   if (init) {
222     GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
223     return;
224   }
225
226   if (list) {
227     ns_iterator = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle,
228                                                          zone,
229                                                          &iter_error,
230                                                          NULL,
231                                                          &iter_cb,
232                                                          NULL,
233                                                          &iter_finished,
234                                                          NULL);
235     return;
236   }
237
238   size = GNUNET_CRYPTO_cpabe_encrypt (attr_value,
239                                       strlen (attr_value) + 1,
240                                       attr_name,
241                                       abe_key,
242                                       (void**)&new_record.data);
243   new_record.data_size = size;
244   new_record.record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
245   new_record.expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
246   new_record.flags = GNUNET_GNSRECORD_RF_NONE;
247
248   ns_qe = GNUNET_NAMESTORE_records_store (namestore_handle,
249                                           zone,
250                                           attr_name,
251                                           1,
252                                           &new_record,
253                                           &store_attr_cont,
254                                           NULL);
255 }
256
257 static void
258 ego_cb (void *cls,
259         struct GNUNET_IDENTITY_Ego *ego,
260         void **ctx,
261         const char *name)
262 {
263   const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey;
264   if (NULL == name)
265     return;
266   if (0 != strcmp (name, ego_name))
267     return;
268   pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
269   ns_qe = GNUNET_NAMESTORE_records_lookup (namestore_handle,
270                                            pkey,
271                                            "+",
272                                            &ns_error_cb,
273                                            NULL,
274                                            &abe_lookup_cb,
275                                            NULL);
276 }
277
278 static void
279 run (void *cls,
280      char *const *args,
281      const char *cfgfile,
282      const struct GNUNET_CONFIGURATION_Handle *c)
283 {
284
285   if (NULL == ego_name)
286   {
287     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
288                 _("Ego is required\n"));
289     return;
290   } 
291
292   if ((NULL == attr_name) && !list && !init)
293   {
294     return;
295   }
296   if ((NULL == attr_value) && !list && !init)
297   {
298     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
299                 _("Value is required\n"));
300     return;
301   }
302
303   namestore_handle = GNUNET_NAMESTORE_connect (c);
304   //Get Ego
305   identity_handle = GNUNET_IDENTITY_connect (c,
306                                              &ego_cb,
307                                              NULL);
308
309
310 }
311
312
313 int
314 main(int argc, char *const argv[])
315 {
316   struct GNUNET_GETOPT_CommandLineOption options[] = {
317
318     GNUNET_GETOPT_option_string ('a',
319                                  "add",
320                                  NULL,
321                                  gettext_noop ("Add attribute"),
322                                  &attr_name),
323
324     GNUNET_GETOPT_option_string ('V',
325                                  "value",
326                                  NULL,
327                                  gettext_noop ("Attribute value"),
328                                  &attr_value),
329     GNUNET_GETOPT_option_string ('e',
330                                  "ego",
331                                  NULL,
332                                  gettext_noop ("Ego"),
333                                  &ego_name),
334     GNUNET_GETOPT_option_flag ('D',
335                                "dump",
336                                gettext_noop ("List attributes for Ego"),
337                                &list),
338     GNUNET_GETOPT_option_flag ('i',
339                                "init",
340                                gettext_noop ("Initialize attribute store"),
341                                &init),
342     GNUNET_GETOPT_OPTION_END
343   };
344   return GNUNET_PROGRAM_run (argc, argv, "ct",
345                              "ct", options,
346                              &run, NULL);
347 }