Merge remote-tracking branch 'origin/master' into credentials
[oweals/gnunet.git] / src / credential / gnunet-credential.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012-2013 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  * @file gnunet-credential.c
22  * @brief command line tool to access command line Credential service
23  * @author Adnan Husain
24  */
25 #include "platform.h"
26 #include <gnunet_util_lib.h>
27 #include <gnunet_identity_service.h>
28 #include <gnunet_credential_service.h>
29
30 /**
31  * Configuration we are using.
32  */
33 static const struct GNUNET_CONFIGURATION_Handle *cfg;
34
35 /**
36  * Handle to Credential service.
37  */
38 static struct GNUNET_CREDENTIAL_Handle *credential;
39
40 /**
41  * Desired timeout for the lookup (default is no timeout).
42  */
43 static struct GNUNET_TIME_Relative timeout;
44
45 /**
46  * Credential to lookup. (-u option)
47  */
48 static char *lookup_credential;
49
50 /**
51  * Handle to verify request
52  */
53 static struct GNUNET_CREDENTIAL_Request *verify_request;
54
55 /**
56  * Lookup an ego with the identity service.
57  */
58 static struct GNUNET_IDENTITY_EgoLookup *el;
59
60 /**
61  * Handle for identity service.
62  */
63 static struct GNUNET_IDENTITY_Handle *identity;
64
65 /**
66  * Active operation on identity service.
67  */
68 static struct GNUNET_IDENTITY_Operation *id_op;
69
70 /**
71  * Task scheduled to handle timeout.
72  */
73 static struct GNUNET_SCHEDULER_Task *tt;
74
75 /**
76  * Subject pubkey string
77  */
78 static char *subject_key;
79
80 /**
81  * Subject pubkey string
82  */
83 static char *issuer_key;
84
85
86
87 /**
88  * Identity of the zone to use for the lookup (-z option)
89  */
90 static char *zone_ego_name;
91
92
93 /**
94  * Task run on shutdown.  Cleans up everything.
95  *
96  * @param cls unused
97  */
98 static void
99 do_shutdown (void *cls)
100 {
101   if (NULL != el)
102   {
103     GNUNET_IDENTITY_ego_lookup_cancel (el);
104     el = NULL;
105   }
106   if (NULL != id_op)
107   {
108     GNUNET_IDENTITY_cancel (id_op);
109     id_op = NULL;
110   }
111   if (NULL != verify_request)
112   {
113     GNUNET_CREDENTIAL_verify_cancel (verify_request);
114     verify_request = NULL;
115   }
116   if (NULL != identity)
117   {
118     GNUNET_IDENTITY_disconnect (identity);
119     identity = NULL;
120   }
121   if (NULL != credential)
122   {
123     GNUNET_CREDENTIAL_disconnect (credential);
124     credential = NULL;
125   }
126   if (NULL != tt)
127   {
128     GNUNET_SCHEDULER_cancel (tt);
129     tt = NULL;
130   }
131 }
132
133
134 /**
135  * Task run on timeout. Triggers shutdown.
136  *
137  * @param cls unused
138  */
139 static void
140 do_timeout (void *cls)
141 {
142   tt = NULL;
143   GNUNET_SCHEDULER_shutdown ();
144 }
145
146
147 /**
148  * Function called with the result of a Credential lookup.
149  *
150  * @param cls the 'const char *' name that was resolved
151  * @param cd_count number of records returned
152  * @param cd array of @a cd_count records with the results
153  */
154 static void
155 handle_verify_result (void *cls,
156                       struct GNUNET_CRYPTO_EcdsaPublicKey *issuer,
157                       uint32_t status)
158 {
159
160
161   verify_request = NULL;
162   if (GNUNET_NO == status)
163     printf ("Verify failed.\n");
164   else
165     printf ("Successful.\n");
166
167
168   GNUNET_SCHEDULER_shutdown ();
169 }
170
171
172
173
174 /**
175  * Perform the actual resolution, with the subject pkey and
176  * the issuer public key
177  *
178  * @param pkey public key to use for the zone, can be NULL
179  * @param shorten_key private key used for shortening, can be NULL
180  */
181 static void
182 lookup_credentials (struct GNUNET_IDENTITY_Ego *ego)
183 {
184
185   struct GNUNET_CRYPTO_EcdsaPublicKey subject_pkey;
186   struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey;
187
188   if (NULL != subject_key && NULL != issuer_key && NULL != lookup_credential)
189   {
190     if (GNUNET_OK !=
191         GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_key,
192                                                     strlen (subject_key),
193                                                     &subject_pkey))
194     {
195       fprintf (stderr,
196                _("Subject public key `%s' is not well-formed\n"),
197                subject_key);
198       GNUNET_SCHEDULER_shutdown ();
199       return;
200     }
201
202     if (GNUNET_OK !=
203         GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
204                                                     strlen (issuer_key),
205                                                     &issuer_pkey))
206     {
207       fprintf (stderr,
208                _("Authority public key `%s' is not well-formed\n"),
209                issuer_key);
210       GNUNET_SCHEDULER_shutdown ();
211       return;
212     }
213
214     verify_request = GNUNET_CREDENTIAL_verify(credential,
215                                               &issuer_pkey,
216                                               "test", //TODO argument
217                                               &subject_pkey,
218                                               lookup_credential,
219                                               &handle_verify_result,
220                                               NULL);
221     return;
222   }
223   else
224   {
225     fprintf (stderr,
226              _("Please specify name to lookup, subject key and issuer key!\n"));
227     GNUNET_SCHEDULER_shutdown ();
228     return;
229   }
230 }
231
232
233 /**
234  * Method called to with the ego we are to use for the lookup,
235  * when the ego is the one for the default master zone.
236  *
237  * @param cls closure (NULL, unused)
238  * @param ego ego handle, NULL if not found
239  * @param ctx context for application to store data for this ego
240  *                 (during the lifetime of this process, initially NULL)
241  * @param name name assigned by the user for this ego,
242  *                   NULL if the user just deleted the ego and it
243  *                   must thus no longer be used
244  */
245 static void
246 identity_master_cb (void *cls,
247                     struct GNUNET_IDENTITY_Ego *ego,
248                     void **ctx,
249                     const char *name)
250 {
251
252   id_op = NULL;
253   if (NULL == ego)
254   {
255     fprintf (stderr,
256              _("Ego for `gns-master' not found, cannot perform lookup.  Did you run gnunet-gns-import.sh?\n"));
257     GNUNET_SCHEDULER_shutdown ();
258     return;
259   }
260
261   lookup_credentials(ego);
262
263
264 }
265
266
267 /**
268  * Main function that will be run.
269  *
270  * @param cls closure
271  * @param args remaining command-line arguments
272  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
273  * @param c configuration
274  */
275 static void
276 run (void *cls,
277      char *const *args,
278      const char *cfgfile,
279      const struct GNUNET_CONFIGURATION_Handle *c)
280 {
281
282   cfg = c;
283   credential = GNUNET_CREDENTIAL_connect (cfg);
284   identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
285
286
287
288
289   if (NULL == credential)
290   {
291     fprintf (stderr,
292              _("Failed to connect to CREDENTIAL\n"));
293     return;
294   }
295   if (NULL == identity)
296   {
297     fprintf (stderr,
298              _("Failed to connect to IDENTITY\n"));
299     return;
300   }
301   tt = GNUNET_SCHEDULER_add_delayed (timeout,
302                                      &do_timeout, NULL);
303   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
304
305
306
307   GNUNET_break (NULL == id_op);
308   id_op = GNUNET_IDENTITY_get (identity,
309                                "gns-master",//# TODO: Create credential-master
310                                &identity_master_cb,
311                                cls);
312   GNUNET_assert (NULL != id_op);
313
314
315
316
317 }
318
319
320 /**
321  * The main function for gnunet-gns.
322  *
323  * @param argc number of arguments from the command line
324  * @param argv command line arguments
325  * @return 0 ok, 1 on error
326  */
327 int
328 main (int argc, char *const *argv)
329 {
330   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
331     {'u', "lookup", "CREDENTIAL",
332       gettext_noop ("Lookup a record for the given credential"), 1,
333       &GNUNET_GETOPT_set_string, &lookup_credential},
334     /** { 'T', "timeout", "DELAY",
335       gettext_noop ("Specify timeout for the lookup"), 1,
336       &GNUNET_GETOPT_set_relative_time, &timeout },
337       {'t', "type", "TYPE",
338       gettext_noop ("Specify the type of the record to lookup"), 1,
339       &GNUNET_GETOPT_set_string, &lookup_type},**/
340     {'z', "zone", "NAME",
341       gettext_noop ("Specify the name of the ego of the zone to lookup the record in"), 1,
342       &GNUNET_GETOPT_set_string, &zone_ego_name},
343     {'s', "subject", "PKEY",
344       gettext_noop ("Specify the public key of the subject to lookup the credential for"), 1,
345       &GNUNET_GETOPT_set_string, &subject_key},
346     {'i', "issuer", "PKEY",
347       gettext_noop ("Specify the public key of the authority to verify the credential against"), 1,
348       &GNUNET_GETOPT_set_string, &issuer_key},
349     GNUNET_GETOPT_OPTION_END
350   };
351   int ret;
352
353   timeout = GNUNET_TIME_UNIT_FOREVER_REL;
354   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
355     return 2;
356
357   GNUNET_log_setup ("gnunet-credential", "WARNING", NULL);
358   ret =
359     (GNUNET_OK ==
360      GNUNET_PROGRAM_run (argc, argv, "gnunet-credential",
361                          _("GNUnet credential resolver tool"),
362                          options,
363                          &run, NULL)) ? 0 : 1;
364   GNUNET_free ((void*) argv);
365   return ret;
366 }
367
368 /* end of gnunet-credential.c */