aboutsummaryrefslogtreecommitdiff
path: root/src/credential/gnunet-credential.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/credential/gnunet-credential.c')
-rw-r--r--src/credential/gnunet-credential.c587
1 files changed, 587 insertions, 0 deletions
diff --git a/src/credential/gnunet-credential.c b/src/credential/gnunet-credential.c
new file mode 100644
index 000000000..fb7bdb7f8
--- /dev/null
+++ b/src/credential/gnunet-credential.c
@@ -0,0 +1,587 @@
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_credential_service.h>
28#include <gnunet_gnsrecord_lib.h>
29#include "credential_misc.h"
30#include "credential_serialization.h"
31
32/**
33 * Configuration we are using.
34 */
35static const struct GNUNET_CONFIGURATION_Handle *cfg;
36
37/**
38 * EgoLookup
39 */
40static struct GNUNET_IDENTITY_EgoLookup *el;
41
42/**
43 * Handle to Credential service.
44 */
45static struct GNUNET_CREDENTIAL_Handle *credential;
46
47/**
48 * Desired timeout for the lookup (default is no timeout).
49 */
50static struct GNUNET_TIME_Relative timeout;
51
52/**
53 * Handle to verify request
54 */
55static struct GNUNET_CREDENTIAL_Request *verify_request;
56
57/**
58 * Handle to collect request
59 */
60static struct GNUNET_CREDENTIAL_Request *collect_request;
61
62/**
63 * Task scheduled to handle timeout.
64 */
65static struct GNUNET_SCHEDULER_Task *tt;
66
67/**
68 * Subject pubkey string
69 */
70static char *subject_key;
71
72/**
73 * Subject credential string
74 */
75static char *subject_credential;
76
77/**
78 * Credential TTL
79 */
80static char *expiration;
81
82/**
83 * Subject key
84 */
85struct GNUNET_CRYPTO_EcdsaPublicKey subject_pkey;
86
87/**
88 * Issuer key
89 */
90struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey;
91
92
93/**
94 * Issuer pubkey string
95 */
96static char *issuer_key;
97
98/**
99 * ego
100 */
101static char *ego_name;
102
103/**
104 * Issuer attribute
105 */
106static char *issuer_attr;
107
108/**
109 * Verify mode
110 */
111static uint32_t verify;
112
113/**
114 * Issue mode
115 */
116static uint32_t create_cred;
117
118/**
119 * Collect mode
120 */
121static uint32_t collect;
122
123/**
124 * Task run on shutdown. Cleans up everything.
125 *
126 * @param cls unused
127 */
128static void
129do_shutdown (void *cls)
130{
131 if (NULL != verify_request)
132 {
133 GNUNET_CREDENTIAL_verify_cancel (verify_request);
134 verify_request = NULL;
135 }
136 if (NULL != credential)
137 {
138 GNUNET_CREDENTIAL_disconnect (credential);
139 credential = NULL;
140 }
141 if (NULL != tt)
142 {
143 GNUNET_SCHEDULER_cancel (tt);
144 tt = NULL;
145 }
146}
147
148
149/**
150 * Task run on timeout. Triggers shutdown.
151 *
152 * @param cls unused
153 */
154static void
155do_timeout (void *cls)
156{
157 tt = NULL;
158 GNUNET_SCHEDULER_shutdown ();
159}
160
161/**
162 * Function called with the result of a Credential lookup.
163 *
164 * @param cls the 'const char *' name that was resolved
165 * @param cd_count number of records returned
166 * @param cd array of @a cd_count records with the results
167 */
168static void
169handle_collect_result (void *cls,
170 unsigned int d_count,
171 struct GNUNET_CREDENTIAL_Delegation *dc,
172 unsigned int c_count,
173 struct GNUNET_CREDENTIAL_Credential *cred)
174{
175 int i;
176 char* line;
177
178 verify_request = NULL;
179 if (NULL != cred)
180 {
181 for (i=0;i<c_count;i++)
182 {
183 line = GNUNET_CREDENTIAL_credential_to_string (&cred[i]);
184 printf ("%s\n",
185 line);
186 GNUNET_free (line);
187 }
188 }
189
190
191 GNUNET_SCHEDULER_shutdown ();
192}
193
194
195/**
196 * Function called with the result of a Credential lookup.
197 *
198 * @param cls the 'const char *' name that was resolved
199 * @param cd_count number of records returned
200 * @param cd array of @a cd_count records with the results
201 */
202static void
203handle_verify_result (void *cls,
204 unsigned int d_count,
205 struct GNUNET_CREDENTIAL_Delegation *dc,
206 unsigned int c_count,
207 struct GNUNET_CREDENTIAL_Credential *cred)
208{
209 int i;
210 char* iss_key;
211 char* sub_key;
212
213 verify_request = NULL;
214 if (NULL == cred)
215 printf ("Failed.\n");
216 else
217 {
218 printf("Delegation Chain:\n");
219 for (i=0;i<d_count;i++)
220 {
221 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].issuer_key);
222 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].subject_key);
223 if (0 != dc[i].subject_attribute_len)
224 {
225 printf ("(%d) %s.%s <- %s.%s\n", i,
226 iss_key, dc[i].issuer_attribute,
227 sub_key, dc[i].subject_attribute);
228 } else {
229 printf ("(%d) %s.%s <- %s\n", i,
230 iss_key, dc[i].issuer_attribute,
231 sub_key);
232 }
233 GNUNET_free (iss_key);
234 GNUNET_free (sub_key);
235 }
236 printf("\nCredentials:\n");
237 for (i=0;i<c_count;i++)
238 {
239 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].issuer_key);
240 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].subject_key);
241 printf ("%s.%s <- %s\n",
242 iss_key, cred[i].issuer_attribute,
243 sub_key);
244 GNUNET_free (iss_key);
245 GNUNET_free (sub_key);
246
247 }
248 printf ("Successful.\n");
249 }
250
251
252 GNUNET_SCHEDULER_shutdown ();
253}
254
255/**
256 * Callback invoked from identity service with ego information.
257 * An @a ego of NULL means the ego was not found.
258 *
259 * @param cls closure with the configuration
260 * @param ego an ego known to identity service, or NULL
261 */
262static void
263identity_cb (void *cls,
264 const struct GNUNET_IDENTITY_Ego *ego)
265{
266 const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
267 struct GNUNET_CREDENTIAL_Credential *crd;
268 struct GNUNET_TIME_Absolute etime_abs;
269 struct GNUNET_TIME_Relative etime_rel;
270 char *res;
271
272 el = NULL;
273 if (NULL == ego)
274 {
275 if (NULL != ego_name)
276 {
277 fprintf (stderr,
278 _("Ego `%s' not known to identity service\n"),
279 ego_name);
280 }
281 GNUNET_SCHEDULER_shutdown ();
282 return;
283 }
284
285 if (GNUNET_YES == collect)
286 {
287
288 if (GNUNET_OK !=
289 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
290 strlen (issuer_key),
291 &issuer_pkey))
292 {
293 fprintf (stderr,
294 _("Issuer public key `%s' is not well-formed\n"),
295 issuer_key);
296 GNUNET_SCHEDULER_shutdown ();
297 }
298 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
299
300 collect_request = GNUNET_CREDENTIAL_collect(credential,
301 &issuer_pkey,
302 issuer_attr, //TODO argument
303 privkey,
304 &handle_collect_result,
305 NULL);
306 return;
307 }
308
309 //Else issue
310
311 if (NULL == expiration)
312 {
313 fprintf (stderr,
314 "Please specify a TTL\n");
315 GNUNET_SCHEDULER_shutdown ();
316 return;
317 } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration,
318 &etime_rel))
319 {
320 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
321 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration,
322 &etime_abs))
323 {
324 fprintf (stderr,
325 "%s is not a valid ttl!\n",
326 expiration);
327 GNUNET_SCHEDULER_shutdown ();
328 return;
329 }
330
331
332 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
333 GNUNET_free_non_null (ego_name);
334 ego_name = NULL;
335 crd = GNUNET_CREDENTIAL_credential_issue (privkey,
336 &subject_pkey,
337 issuer_attr,
338 &etime_abs);
339
340 res = GNUNET_CREDENTIAL_credential_to_string (crd);
341 GNUNET_free (crd);
342 printf ("%s\n", res);
343 GNUNET_SCHEDULER_shutdown ();
344}
345
346
347
348
349/**
350 * Main function that will be run.
351 *
352 * @param cls closure
353 * @param args remaining command-line arguments
354 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
355 * @param c configuration
356 */
357static void
358run (void *cls,
359 char *const *args,
360 const char *cfgfile,
361 const struct GNUNET_CONFIGURATION_Handle *c)
362{
363
364 cfg = c;
365
366
367 tt = GNUNET_SCHEDULER_add_delayed (timeout,
368 &do_timeout, NULL);
369 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
370
371 if (GNUNET_YES == collect) {
372 if (NULL == issuer_key)
373 {
374 fprintf (stderr,
375 _("Issuer public key not well-formed\n"));
376 GNUNET_SCHEDULER_shutdown ();
377 return;
378
379 }
380
381 credential = GNUNET_CREDENTIAL_connect (cfg);
382
383 if (NULL == credential)
384 {
385 fprintf (stderr,
386 _("Failed to connect to CREDENTIAL\n"));
387 GNUNET_SCHEDULER_shutdown ();
388 }
389 if (NULL == issuer_attr)
390 {
391 fprintf (stderr,
392 _("You must provide issuer the attribute\n"));
393 GNUNET_SCHEDULER_shutdown ();
394 }
395
396 if (NULL == ego_name)
397 {
398 fprintf (stderr,
399 _("ego required\n"));
400 GNUNET_SCHEDULER_shutdown ();
401 return;
402
403 }
404 el = GNUNET_IDENTITY_ego_lookup (cfg,
405 ego_name,
406 &identity_cb,
407 (void *) cfg);
408 return;
409
410 }
411
412 if (NULL == subject_key)
413 {
414 fprintf (stderr,
415 _("Subject public key needed\n"));
416 GNUNET_SCHEDULER_shutdown ();
417 return;
418
419 }
420 if (GNUNET_OK !=
421 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_key,
422 strlen (subject_key),
423 &subject_pkey))
424 {
425 fprintf (stderr,
426 _("Subject public key `%s' is not well-formed\n"),
427 subject_key);
428 GNUNET_SCHEDULER_shutdown ();
429 return;
430 }
431 if (GNUNET_YES == verify) {
432 if (NULL == issuer_key)
433 {
434 fprintf (stderr,
435 _("Issuer public key not well-formed\n"));
436 GNUNET_SCHEDULER_shutdown ();
437 return;
438
439 }
440 if (GNUNET_OK !=
441 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
442 strlen (issuer_key),
443 &issuer_pkey))
444 {
445 fprintf (stderr,
446 _("Issuer public key `%s' is not well-formed\n"),
447 issuer_key);
448 GNUNET_SCHEDULER_shutdown ();
449 }
450 credential = GNUNET_CREDENTIAL_connect (cfg);
451
452 if (NULL == credential)
453 {
454 fprintf (stderr,
455 _("Failed to connect to CREDENTIAL\n"));
456 GNUNET_SCHEDULER_shutdown ();
457 }
458 if (NULL == issuer_attr || NULL == subject_credential)
459 {
460 fprintf (stderr,
461 _("You must provide issuer and subject attributes\n"));
462 GNUNET_SCHEDULER_shutdown ();
463 }
464
465 //Subject credentials are comma separated
466 char *tmp = GNUNET_strdup (subject_credential);
467 char *tok = strtok (tmp, ",");
468 if (NULL == tok)
469 {
470 fprintf (stderr,
471 "Invalid subject credentials\n");
472 GNUNET_free (tmp);
473 GNUNET_SCHEDULER_shutdown ();
474 }
475 int count = 1;
476 int i;
477 while (NULL != (tok = strtok(NULL, ",")))
478 count++;
479 struct GNUNET_CREDENTIAL_Credential credentials[count];
480 struct GNUNET_CREDENTIAL_Credential *cred;
481 GNUNET_free (tmp);
482 tmp = GNUNET_strdup (subject_credential);
483 tok = strtok (tmp, ",");
484 for (i=0;i<count;i++)
485 {
486 cred = GNUNET_CREDENTIAL_credential_from_string (tok);
487 GNUNET_memcpy (&credentials[i],
488 cred,
489 sizeof (struct GNUNET_CREDENTIAL_Credential));
490 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
491 tok = strtok(NULL, ",");
492 GNUNET_free (cred);
493 }
494
495 verify_request = GNUNET_CREDENTIAL_verify(credential,
496 &issuer_pkey,
497 issuer_attr, //TODO argument
498 &subject_pkey,
499 count,
500 credentials,
501 &handle_verify_result,
502 NULL);
503 for (i=0;i<count;i++)
504 {
505 GNUNET_free ((char*)credentials[i].issuer_attribute);
506 }
507 } else if (GNUNET_YES == create_cred) {
508 if (NULL == ego_name)
509 {
510 fprintf (stderr,
511 _("Issuer ego required\n"));
512 GNUNET_SCHEDULER_shutdown ();
513 return;
514
515 }
516 el = GNUNET_IDENTITY_ego_lookup (cfg,
517 ego_name,
518 &identity_cb,
519 (void *) cfg);
520 return;
521 } else {
522 fprintf (stderr,
523 _("Please specify name to lookup, subject key and issuer key!\n"));
524 GNUNET_SCHEDULER_shutdown ();
525 }
526 return;
527}
528
529
530/**
531 * The main function for gnunet-gns.
532 *
533 * @param argc number of arguments from the command line
534 * @param argv command line arguments
535 * @return 0 ok, 1 on error
536 */
537int
538main (int argc, char *const *argv)
539{
540 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
541 {'I', "issue", NULL,
542 gettext_noop ("create credential"), 0,
543 &GNUNET_GETOPT_set_one, &create_cred},
544 {'V', "verify", NULL,
545 gettext_noop ("verify credential against attribute"), 0,
546 &GNUNET_GETOPT_set_one, &verify},
547 {'s', "subject", "PKEY",
548 gettext_noop ("The public key of the subject to lookup the credential for"), 1,
549 &GNUNET_GETOPT_set_string, &subject_key},
550 {'b', "credential", "CRED",
551 gettext_noop ("The name of the credential presented by the subject"), 1,
552 &GNUNET_GETOPT_set_string, &subject_credential},
553 {'i', "issuer", "PKEY",
554 gettext_noop ("The public key of the authority to verify the credential against"), 1,
555 &GNUNET_GETOPT_set_string, &issuer_key},
556 {'e', "ego", "EGO",
557 gettext_noop ("The ego to use"), 1,
558 &GNUNET_GETOPT_set_string, &ego_name},
559 {'a', "attribute", "ATTR",
560 gettext_noop ("The issuer attribute to verify against or to issue"), 1,
561 &GNUNET_GETOPT_set_string, &issuer_attr},
562 {'T', "ttl", "EXP",
563 gettext_noop ("The time to live for the credential"), 1,
564 &GNUNET_GETOPT_set_string, &expiration},
565 {'g', "collect", NULL,
566 gettext_noop ("collect credentials"), 0,
567 &GNUNET_GETOPT_set_one, &collect},
568 GNUNET_GETOPT_OPTION_END
569 };
570 int ret;
571
572 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
573 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
574 return 2;
575
576 GNUNET_log_setup ("gnunet-credential", "WARNING", NULL);
577 ret =
578 (GNUNET_OK ==
579 GNUNET_PROGRAM_run (argc, argv, "gnunet-credential",
580 _("GNUnet credential resolver tool"),
581 options,
582 &run, NULL)) ? 0 : 1;
583 GNUNET_free ((void*) argv);
584 return ret;
585}
586
587/* end of gnunet-credential.c */