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.c588
1 files changed, 588 insertions, 0 deletions
diff --git a/src/credential/gnunet-credential.c b/src/credential/gnunet-credential.c
new file mode 100644
index 000000000..03f959b95
--- /dev/null
+++ b/src/credential/gnunet-credential.c
@@ -0,0 +1,588 @@
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 Martin Schanzenbach
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 int verify;
112
113/**
114 * Issue mode
115 */
116static int create_cred;
117
118/**
119 * Collect mode
120 */
121static int 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_request_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
161static void
162handle_collect_result (void *cls,
163 unsigned int d_count,
164 struct GNUNET_CREDENTIAL_Delegation *dc,
165 unsigned int c_count,
166 struct GNUNET_CREDENTIAL_Credential *cred)
167{
168 int i;
169 char* line;
170
171 verify_request = NULL;
172 if (NULL != cred)
173 {
174 for (i=0;i<c_count;i++)
175 {
176 line = GNUNET_CREDENTIAL_credential_to_string (&cred[i]);
177 printf ("%s\n",
178 line);
179 GNUNET_free (line);
180 }
181 }
182
183
184 GNUNET_SCHEDULER_shutdown ();
185}
186
187
188static void
189handle_verify_result (void *cls,
190 unsigned int d_count,
191 struct GNUNET_CREDENTIAL_Delegation *dc,
192 unsigned int c_count,
193 struct GNUNET_CREDENTIAL_Credential *cred)
194{
195 int i;
196 char* iss_key;
197 char* sub_key;
198
199 verify_request = NULL;
200 if (NULL == cred)
201 printf ("Failed.\n");
202 else
203 {
204 printf("Delegation Chain:\n");
205 for (i=0;i<d_count;i++)
206 {
207 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].issuer_key);
208 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].subject_key);
209 if (0 != dc[i].subject_attribute_len)
210 {
211 printf ("(%d) %s.%s <- %s.%s\n", i,
212 iss_key, dc[i].issuer_attribute,
213 sub_key, dc[i].subject_attribute);
214 } else {
215 printf ("(%d) %s.%s <- %s\n", i,
216 iss_key, dc[i].issuer_attribute,
217 sub_key);
218 }
219 GNUNET_free (iss_key);
220 GNUNET_free (sub_key);
221 }
222 printf("\nCredentials:\n");
223 for (i=0;i<c_count;i++)
224 {
225 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].issuer_key);
226 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].subject_key);
227 printf ("%s.%s <- %s\n",
228 iss_key, cred[i].issuer_attribute,
229 sub_key);
230 GNUNET_free (iss_key);
231 GNUNET_free (sub_key);
232
233 }
234 printf ("Successful.\n");
235 }
236
237
238 GNUNET_SCHEDULER_shutdown ();
239}
240
241/**
242 * Callback invoked from identity service with ego information.
243 * An @a ego of NULL means the ego was not found.
244 *
245 * @param cls closure with the configuration
246 * @param ego an ego known to identity service, or NULL
247 */
248static void
249identity_cb (void *cls,
250 const struct GNUNET_IDENTITY_Ego *ego)
251{
252 const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
253 struct GNUNET_CREDENTIAL_Credential *crd;
254 struct GNUNET_TIME_Absolute etime_abs;
255 struct GNUNET_TIME_Relative etime_rel;
256 char *res;
257
258 el = NULL;
259 if (NULL == ego)
260 {
261 if (NULL != ego_name)
262 {
263 fprintf (stderr,
264 _("Ego `%s' not known to identity service\n"),
265 ego_name);
266 }
267 GNUNET_SCHEDULER_shutdown ();
268 return;
269 }
270
271 if (GNUNET_YES == collect)
272 {
273
274 if (GNUNET_OK !=
275 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
276 strlen (issuer_key),
277 &issuer_pkey))
278 {
279 fprintf (stderr,
280 _("Issuer public key `%s' is not well-formed\n"),
281 issuer_key);
282 GNUNET_SCHEDULER_shutdown ();
283 }
284 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
285
286 collect_request = GNUNET_CREDENTIAL_collect(credential,
287 &issuer_pkey,
288 issuer_attr, //TODO argument
289 privkey,
290 &handle_collect_result,
291 NULL);
292 return;
293 }
294
295 //Else issue
296
297 if (NULL == expiration)
298 {
299 fprintf (stderr,
300 "Please specify a TTL\n");
301 GNUNET_SCHEDULER_shutdown ();
302 return;
303 } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration,
304 &etime_rel))
305 {
306 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
307 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration,
308 &etime_abs))
309 {
310 fprintf (stderr,
311 "%s is not a valid ttl!\n",
312 expiration);
313 GNUNET_SCHEDULER_shutdown ();
314 return;
315 }
316
317
318 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
319 GNUNET_free_non_null (ego_name);
320 ego_name = NULL;
321 crd = GNUNET_CREDENTIAL_credential_issue (privkey,
322 &subject_pkey,
323 issuer_attr,
324 &etime_abs);
325
326 res = GNUNET_CREDENTIAL_credential_to_string (crd);
327 GNUNET_free (crd);
328 printf ("%s\n", res);
329 GNUNET_SCHEDULER_shutdown ();
330}
331
332
333
334
335/**
336 * Main function that will be run.
337 *
338 * @param cls closure
339 * @param args remaining command-line arguments
340 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
341 * @param c configuration
342 */
343static void
344run (void *cls,
345 char *const *args,
346 const char *cfgfile,
347 const struct GNUNET_CONFIGURATION_Handle *c)
348{
349
350 cfg = c;
351
352
353 tt = GNUNET_SCHEDULER_add_delayed (timeout,
354 &do_timeout, NULL);
355 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
356
357 if (GNUNET_YES == collect) {
358 if (NULL == issuer_key)
359 {
360 fprintf (stderr,
361 _("Issuer public key not well-formed\n"));
362 GNUNET_SCHEDULER_shutdown ();
363 return;
364
365 }
366
367 credential = GNUNET_CREDENTIAL_connect (cfg);
368
369 if (NULL == credential)
370 {
371 fprintf (stderr,
372 _("Failed to connect to CREDENTIAL\n"));
373 GNUNET_SCHEDULER_shutdown ();
374 }
375 if (NULL == issuer_attr)
376 {
377 fprintf (stderr,
378 _("You must provide issuer the attribute\n"));
379 GNUNET_SCHEDULER_shutdown ();
380 }
381
382 if (NULL == ego_name)
383 {
384 fprintf (stderr,
385 _("ego required\n"));
386 GNUNET_SCHEDULER_shutdown ();
387 return;
388
389 }
390 el = GNUNET_IDENTITY_ego_lookup (cfg,
391 ego_name,
392 &identity_cb,
393 (void *) cfg);
394 return;
395
396 }
397
398 if (NULL == subject_key)
399 {
400 fprintf (stderr,
401 _("Subject public key needed\n"));
402 GNUNET_SCHEDULER_shutdown ();
403 return;
404
405 }
406 if (GNUNET_OK !=
407 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_key,
408 strlen (subject_key),
409 &subject_pkey))
410 {
411 fprintf (stderr,
412 _("Subject public key `%s' is not well-formed\n"),
413 subject_key);
414 GNUNET_SCHEDULER_shutdown ();
415 return;
416 }
417 if (GNUNET_YES == verify) {
418 if (NULL == issuer_key)
419 {
420 fprintf (stderr,
421 _("Issuer public key not well-formed\n"));
422 GNUNET_SCHEDULER_shutdown ();
423 return;
424
425 }
426 if (GNUNET_OK !=
427 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
428 strlen (issuer_key),
429 &issuer_pkey))
430 {
431 fprintf (stderr,
432 _("Issuer public key `%s' is not well-formed\n"),
433 issuer_key);
434 GNUNET_SCHEDULER_shutdown ();
435 }
436 credential = GNUNET_CREDENTIAL_connect (cfg);
437
438 if (NULL == credential)
439 {
440 fprintf (stderr,
441 _("Failed to connect to CREDENTIAL\n"));
442 GNUNET_SCHEDULER_shutdown ();
443 }
444 if (NULL == issuer_attr || NULL == subject_credential)
445 {
446 fprintf (stderr,
447 _("You must provide issuer and subject attributes\n"));
448 GNUNET_SCHEDULER_shutdown ();
449 }
450
451 //Subject credentials are comma separated
452 char *tmp = GNUNET_strdup (subject_credential);
453 char *tok = strtok (tmp, ",");
454 if (NULL == tok)
455 {
456 fprintf (stderr,
457 "Invalid subject credentials\n");
458 GNUNET_free (tmp);
459 GNUNET_SCHEDULER_shutdown ();
460 }
461 int count = 1;
462 int i;
463 while (NULL != (tok = strtok(NULL, ",")))
464 count++;
465 struct GNUNET_CREDENTIAL_Credential credentials[count];
466 struct GNUNET_CREDENTIAL_Credential *cred;
467 GNUNET_free (tmp);
468 tmp = GNUNET_strdup (subject_credential);
469 tok = strtok (tmp, ",");
470 for (i=0;i<count;i++)
471 {
472 cred = GNUNET_CREDENTIAL_credential_from_string (tok);
473 GNUNET_memcpy (&credentials[i],
474 cred,
475 sizeof (struct GNUNET_CREDENTIAL_Credential));
476 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
477 tok = strtok(NULL, ",");
478 GNUNET_free (cred);
479 }
480
481 verify_request = GNUNET_CREDENTIAL_verify(credential,
482 &issuer_pkey,
483 issuer_attr, //TODO argument
484 &subject_pkey,
485 count,
486 credentials,
487 &handle_verify_result,
488 NULL);
489 for (i=0;i<count;i++)
490 {
491 GNUNET_free ((char*)credentials[i].issuer_attribute);
492 }
493 } else if (GNUNET_YES == create_cred) {
494 if (NULL == ego_name)
495 {
496 fprintf (stderr,
497 _("Issuer ego required\n"));
498 GNUNET_SCHEDULER_shutdown ();
499 return;
500
501 }
502 el = GNUNET_IDENTITY_ego_lookup (cfg,
503 ego_name,
504 &identity_cb,
505 (void *) cfg);
506 return;
507 } else {
508 fprintf (stderr,
509 _("Please specify name to lookup, subject key and issuer key!\n"));
510 GNUNET_SCHEDULER_shutdown ();
511 }
512 return;
513}
514
515
516/**
517 * The main function for gnunet-gns.
518 *
519 * @param argc number of arguments from the command line
520 * @param argv command line arguments
521 * @return 0 ok, 1 on error
522 */
523int
524main (int argc, char *const *argv)
525{
526 struct GNUNET_GETOPT_CommandLineOption options[] = {
527 GNUNET_GETOPT_option_flag ('I',
528 "issue",
529 gettext_noop ("create credential"),
530 &create_cred),
531 GNUNET_GETOPT_option_flag ('V',
532 "verify",
533 gettext_noop ("verify credential against attribute"),
534 &verify),
535 GNUNET_GETOPT_option_string ('s',
536 "subject",
537 "PKEY",
538 gettext_noop ("The public key of the subject to lookup the credential for"),
539 &subject_key),
540 GNUNET_GETOPT_option_string ('b',
541 "credential",
542 "CRED",
543 gettext_noop ("The name of the credential presented by the subject"),
544 &subject_credential),
545 GNUNET_GETOPT_option_string ('i',
546 "issuer",
547 "PKEY",
548 gettext_noop ("The public key of the authority to verify the credential against"),
549 &issuer_key),
550 GNUNET_GETOPT_option_string ('e',
551 "ego",
552 "EGO",
553 gettext_noop ("The ego to use"),
554 &ego_name),
555 GNUNET_GETOPT_option_string ('a',
556 "attribute",
557 "ATTR",
558 gettext_noop ("The issuer attribute to verify against or to issue"),
559 &issuer_attr),
560 GNUNET_GETOPT_option_string ('T',
561 "ttl",
562 "EXP",
563 gettext_noop ("The time to live for the credential"),
564 &expiration),
565 GNUNET_GETOPT_option_flag ('g',
566 "collect",
567 gettext_noop ("collect credentials"),
568 &collect),
569 GNUNET_GETOPT_OPTION_END
570 };
571 int ret;
572
573 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
574 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
575 return 2;
576
577 GNUNET_log_setup ("gnunet-credential", "WARNING", NULL);
578 ret =
579 (GNUNET_OK ==
580 GNUNET_PROGRAM_run (argc, argv, "gnunet-credential",
581 _("GNUnet credential resolver tool"),
582 options,
583 &run, NULL)) ? 0 : 1;
584 GNUNET_free ((void*) argv);
585 return ret;
586}
587
588/* end of gnunet-credential.c */