diff options
author | Schanzenbach, Martin <mschanzenbach@posteo.de> | 2017-07-08 20:02:12 +0200 |
---|---|---|
committer | Schanzenbach, Martin <mschanzenbach@posteo.de> | 2017-07-08 20:02:12 +0200 |
commit | d43a25d25ad68fcc1508e8fcf092c5014a6bdba8 (patch) | |
tree | 8d8917eb5ed8768d665bc100eb72821522efbf2c /src | |
parent | 591432f733943cdc24110d4b582f60351afb9c05 (diff) | |
download | gnunet-d43a25d25ad68fcc1508e8fcf092c5014a6bdba8.tar.gz gnunet-d43a25d25ad68fcc1508e8fcf092c5014a6bdba8.zip |
-towards IdP2
Diffstat (limited to 'src')
-rw-r--r-- | src/identity-provider/gnunet-service-identity-provider.c | 768 | ||||
-rw-r--r-- | src/include/gnunet_gnsrecord_lib.h | 4 |
2 files changed, 123 insertions, 649 deletions
diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c index f4ea352d4..3a7a6eeb9 100644 --- a/src/identity-provider/gnunet-service-identity-provider.c +++ b/src/identity-provider/gnunet-service-identity-provider.c | |||
@@ -59,21 +59,6 @@ | |||
59 | #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS | 59 | #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS |
60 | 60 | ||
61 | /** | 61 | /** |
62 | * Service state (to detect initial update pass) | ||
63 | */ | ||
64 | static int state; | ||
65 | |||
66 | /** | ||
67 | * Head of ego entry DLL | ||
68 | */ | ||
69 | static struct EgoEntry *ego_head; | ||
70 | |||
71 | /** | ||
72 | * Tail of ego entry DLL | ||
73 | */ | ||
74 | static struct EgoEntry *ego_tail; | ||
75 | |||
76 | /** | ||
77 | * Identity handle | 62 | * Identity handle |
78 | */ | 63 | */ |
79 | static struct GNUNET_IDENTITY_Handle *identity_handle; | 64 | static struct GNUNET_IDENTITY_Handle *identity_handle; |
@@ -118,11 +103,6 @@ static struct GNUNET_SCHEDULER_Task *timeout_task; | |||
118 | */ | 103 | */ |
119 | static struct GNUNET_SCHEDULER_Task *update_task; | 104 | static struct GNUNET_SCHEDULER_Task *update_task; |
120 | 105 | ||
121 | /** | ||
122 | * Timeout for next update pass | ||
123 | */ | ||
124 | static struct GNUNET_TIME_Relative min_rel_exp; | ||
125 | |||
126 | 106 | ||
127 | /** | 107 | /** |
128 | * Currently processed token | 108 | * Currently processed token |
@@ -140,16 +120,6 @@ static char* label; | |||
140 | static char* scopes; | 120 | static char* scopes; |
141 | 121 | ||
142 | /** | 122 | /** |
143 | * Expiration for processed token | ||
144 | */ | ||
145 | static uint64_t rd_exp; | ||
146 | |||
147 | /** | ||
148 | * ECDHE Privkey for processed token metadata | ||
149 | */ | ||
150 | static struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_privkey; | ||
151 | |||
152 | /** | ||
153 | * Handle to the statistics service. | 123 | * Handle to the statistics service. |
154 | */ | 124 | */ |
155 | static struct GNUNET_STATISTICS_Handle *stats; | 125 | static struct GNUNET_STATISTICS_Handle *stats; |
@@ -240,6 +210,11 @@ struct IssueHandle | |||
240 | struct GNUNET_CRYPTO_EcdsaPublicKey aud_key; | 210 | struct GNUNET_CRYPTO_EcdsaPublicKey aud_key; |
241 | 211 | ||
242 | /** | 212 | /** |
213 | * The issuer egos ABE master key | ||
214 | */ | ||
215 | struct GNUNET_CRYPTO_AbeMasterKey *abe_key; | ||
216 | |||
217 | /** | ||
243 | * Expiration | 218 | * Expiration |
244 | */ | 219 | */ |
245 | struct GNUNET_TIME_Absolute expiration; | 220 | struct GNUNET_TIME_Absolute expiration; |
@@ -331,574 +306,14 @@ struct EgoEntry | |||
331 | */ | 306 | */ |
332 | struct GNUNET_CONTAINER_MultiHashMap *attr_map; | 307 | struct GNUNET_CONTAINER_MultiHashMap *attr_map; |
333 | 308 | ||
334 | /** | ||
335 | * Attributes are old and should be updated if GNUNET_YES | ||
336 | */ | ||
337 | int attributes_dirty; | ||
338 | }; | 309 | }; |
339 | 310 | ||
340 | /** | 311 | /** |
341 | * Continuation for token store call | ||
342 | * | ||
343 | * @param cls NULL | ||
344 | * @param success error code | ||
345 | * @param emsg error message | ||
346 | */ | ||
347 | static void | ||
348 | store_token_cont (void *cls, | ||
349 | int32_t success, | ||
350 | const char *emsg) | ||
351 | { | ||
352 | ns_qe = NULL; | ||
353 | if (GNUNET_SYSERR == success) | ||
354 | { | ||
355 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
356 | "Failed to update token: %s\n", | ||
357 | emsg); | ||
358 | return; | ||
359 | } | ||
360 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | ||
361 | } | ||
362 | |||
363 | |||
364 | /** | ||
365 | * This function updates the old token with new attributes, | ||
366 | * removes deleted attributes and expiration times. | ||
367 | * | ||
368 | * @param cls the ego entry | ||
369 | */ | ||
370 | static void | ||
371 | handle_token_update (void *cls) | ||
372 | { | ||
373 | char *token_metadata; | ||
374 | char *write_ptr; | ||
375 | char *enc_token_str; | ||
376 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | ||
377 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | ||
378 | struct GNUNET_CRYPTO_EcdhePrivateKey *new_ecdhe_privkey; | ||
379 | struct EgoEntry *ego_entry = cls; | ||
380 | struct GNUNET_GNSRECORD_Data token_record[2]; | ||
381 | struct GNUNET_HashCode key_hash; | ||
382 | struct GNUNET_TIME_Relative token_rel_exp; | ||
383 | struct GNUNET_TIME_Relative token_ttl; | ||
384 | struct GNUNET_TIME_Absolute token_exp; | ||
385 | struct GNUNET_TIME_Absolute token_nbf; | ||
386 | struct GNUNET_TIME_Absolute new_exp; | ||
387 | struct GNUNET_TIME_Absolute new_iat; | ||
388 | struct GNUNET_TIME_Absolute new_nbf; | ||
389 | struct IdentityToken *new_token; | ||
390 | struct TokenAttr *cur_value; | ||
391 | struct TokenAttr *attr; | ||
392 | size_t token_metadata_len; | ||
393 | |||
394 | priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
395 | GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, | ||
396 | &pub_key); | ||
397 | |||
398 | //Note: We need the token expiration time here. Not the record expiration | ||
399 | //time. | ||
400 | //There are two types of tokens: Token that expire on GNS level with | ||
401 | //an absolute expiration time. Those are basically tokens that will | ||
402 | //be automatically revoked on (record)expiration. | ||
403 | //Tokens stored with relative expiration times will expire on the token level (token expiration) | ||
404 | //but this service will reissue new tokens that can be retrieved from GNS | ||
405 | //automatically. | ||
406 | |||
407 | for (attr = token->attr_head; NULL != attr; attr = attr->next) | ||
408 | { | ||
409 | if (0 == strcmp (attr->name, "exp")) | ||
410 | { | ||
411 | GNUNET_assert (1 == sscanf (attr->val_head->value, | ||
412 | "%"SCNu64, | ||
413 | &token_exp.abs_value_us)); | ||
414 | } else if (0 == strcmp (attr->name, "nbf")) { | ||
415 | GNUNET_assert (1 == sscanf (attr->val_head->value, | ||
416 | "%"SCNu64, | ||
417 | &token_nbf.abs_value_us)); | ||
418 | } | ||
419 | } | ||
420 | token_rel_exp = GNUNET_TIME_absolute_get_difference (token_nbf, token_exp); | ||
421 | |||
422 | token_ttl = GNUNET_TIME_absolute_get_remaining (token_exp); | ||
423 | if (0 != GNUNET_TIME_absolute_get_remaining (token_exp).rel_value_us) | ||
424 | { | ||
425 | //This token is not yet expired! Save and skip | ||
426 | if (min_rel_exp.rel_value_us > token_ttl.rel_value_us) | ||
427 | { | ||
428 | min_rel_exp = token_ttl; | ||
429 | } | ||
430 | GNUNET_free (token); | ||
431 | token = NULL; | ||
432 | GNUNET_free (label); | ||
433 | label = NULL; | ||
434 | GNUNET_free (scopes); | ||
435 | scopes = NULL; | ||
436 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | ||
437 | return; | ||
438 | } | ||
439 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
440 | "Token is expired. Create a new one\n"); | ||
441 | new_token = token_create (&pub_key, | ||
442 | &token->aud_key); | ||
443 | new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp); | ||
444 | new_nbf = GNUNET_TIME_absolute_get (); | ||
445 | new_iat = new_nbf; | ||
446 | for (attr = token->attr_head; NULL != attr; attr = attr->next) | ||
447 | { | ||
448 | if (0 == strcmp (attr->name, "exp")) | ||
449 | { | ||
450 | token_add_attr_int (new_token, attr->name, new_exp.abs_value_us); | ||
451 | } | ||
452 | else if (0 == strcmp (attr->name, "nbf")) | ||
453 | { | ||
454 | token_add_attr_int (new_token, attr->name, new_nbf.abs_value_us); | ||
455 | } | ||
456 | else if (0 == strcmp (attr->name, "iat")) | ||
457 | { | ||
458 | token_add_attr_int (new_token, attr->name, new_iat.abs_value_us); | ||
459 | } | ||
460 | else if ((0 == strcmp (attr->name, "iss")) | ||
461 | || (0 == strcmp (attr->name, "aud"))) | ||
462 | { | ||
463 | //Omit | ||
464 | } | ||
465 | else if (0 == strcmp (attr->name, "sub")) | ||
466 | { | ||
467 | token_add_attr (new_token, | ||
468 | attr->name, | ||
469 | attr->val_head->value); | ||
470 | } | ||
471 | else | ||
472 | { | ||
473 | GNUNET_CRYPTO_hash (attr->name, | ||
474 | strlen (attr->name), | ||
475 | &key_hash); | ||
476 | //Check if attr still exists. omit of not | ||
477 | if (GNUNET_NO != | ||
478 | GNUNET_CONTAINER_multihashmap_contains (ego_entry->attr_map, | ||
479 | &key_hash)) | ||
480 | { | ||
481 | cur_value = GNUNET_CONTAINER_multihashmap_get (ego_entry->attr_map, | ||
482 | &key_hash); | ||
483 | GNUNET_assert (NULL != cur_value); | ||
484 | GNUNET_CONTAINER_DLL_insert (new_token->attr_head, | ||
485 | new_token->attr_tail, | ||
486 | cur_value); | ||
487 | } | ||
488 | } | ||
489 | } | ||
490 | |||
491 | // reassemble and set | ||
492 | GNUNET_assert (token_serialize (new_token, | ||
493 | priv_key, | ||
494 | &new_ecdhe_privkey, | ||
495 | &enc_token_str)); | ||
496 | |||
497 | token_record[0].data = enc_token_str; | ||
498 | token_record[0].data_size = strlen (enc_token_str) + 1; | ||
499 | token_record[0].expiration_time = rd_exp; //Old expiration time | ||
500 | token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN; | ||
501 | token_record[0].flags = GNUNET_GNSRECORD_RF_NONE; | ||
502 | |||
503 | //Meta | ||
504 | token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey) | ||
505 | + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) | ||
506 | + strlen (scopes) + 1; //With 0-Terminator | ||
507 | token_metadata = GNUNET_malloc (token_metadata_len); | ||
508 | write_ptr = token_metadata; | ||
509 | GNUNET_memcpy (token_metadata, new_ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); | ||
510 | write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); | ||
511 | GNUNET_memcpy (write_ptr, &token->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
512 | write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); | ||
513 | GNUNET_memcpy (write_ptr, scopes, strlen (scopes) + 1); //with 0-Terminator; | ||
514 | |||
515 | token_record[1].data = token_metadata; | ||
516 | token_record[1].data_size = token_metadata_len; | ||
517 | token_record[1].expiration_time = rd_exp; | ||
518 | token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA; | ||
519 | token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE; | ||
520 | |||
521 | ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
522 | priv_key, | ||
523 | label, | ||
524 | 2, | ||
525 | token_record, | ||
526 | &store_token_cont, | ||
527 | ego_entry); | ||
528 | token_destroy (new_token); | ||
529 | token_destroy (token); | ||
530 | GNUNET_free (new_ecdhe_privkey); | ||
531 | GNUNET_free (enc_token_str); | ||
532 | token = NULL; | ||
533 | GNUNET_free (label); | ||
534 | label = NULL; | ||
535 | GNUNET_free (scopes); | ||
536 | scopes = NULL; | ||
537 | } | ||
538 | |||
539 | |||
540 | static void | ||
541 | update_identities(void *cls); | ||
542 | |||
543 | |||
544 | /** | ||
545 | * | ||
546 | * Cleanup attr_map | ||
547 | * | ||
548 | * @param cls NULL | ||
549 | * @param key the key | ||
550 | * @param value the json_t attribute value | ||
551 | * @return #GNUNET_YES | ||
552 | */ | ||
553 | static int | ||
554 | clear_ego_attrs (void *cls, | ||
555 | const struct GNUNET_HashCode *key, | ||
556 | void *value) | ||
557 | { | ||
558 | struct TokenAttr *attr = value; | ||
559 | struct TokenAttrValue *val; | ||
560 | struct TokenAttrValue *tmp_val; | ||
561 | for (val = attr->val_head; NULL != val;) | ||
562 | { | ||
563 | tmp_val = val->next; | ||
564 | GNUNET_CONTAINER_DLL_remove (attr->val_head, | ||
565 | attr->val_tail, | ||
566 | val); | ||
567 | GNUNET_free (val->value); | ||
568 | GNUNET_free (val); | ||
569 | val = tmp_val; | ||
570 | } | ||
571 | GNUNET_free (attr->name); | ||
572 | GNUNET_free (attr); | ||
573 | |||
574 | return GNUNET_YES; | ||
575 | } | ||
576 | |||
577 | |||
578 | static void | ||
579 | token_collect_error_cb (void *cls) | ||
580 | { | ||
581 | struct EgoEntry *ego_entry = cls; | ||
582 | |||
583 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
584 | ">>> Updating Ego failed!\n"); | ||
585 | //Clear attribute map for ego | ||
586 | GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map, | ||
587 | &clear_ego_attrs, | ||
588 | ego_entry); | ||
589 | GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map); | ||
590 | update_task = GNUNET_SCHEDULER_add_now (&update_identities, | ||
591 | ego_entry->next); | ||
592 | |||
593 | } | ||
594 | |||
595 | |||
596 | static void | ||
597 | token_collect_finished_cb (void *cls) | ||
598 | { | ||
599 | struct EgoEntry *ego_entry = cls; | ||
600 | |||
601 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
602 | ">>> Updating Ego finished\n"); | ||
603 | //Clear attribute map for ego | ||
604 | GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map, | ||
605 | &clear_ego_attrs, | ||
606 | ego_entry); | ||
607 | GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map); | ||
608 | update_task = GNUNET_SCHEDULER_add_now (&update_identities, | ||
609 | ego_entry->next); | ||
610 | } | ||
611 | |||
612 | |||
613 | /** | ||
614 | * | ||
615 | * Update all ID_TOKEN records for an identity and store them | ||
616 | * | ||
617 | * @param cls the identity entry | ||
618 | * @param zone the identity | ||
619 | * @param lbl the name of the record | ||
620 | * @param rd_count number of records | ||
621 | * @param rd record data | ||
622 | */ | ||
623 | static void | ||
624 | token_collect (void *cls, | ||
625 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | ||
626 | const char *lbl, | ||
627 | unsigned int rd_count, | ||
628 | const struct GNUNET_GNSRECORD_Data *rd) | ||
629 | { | ||
630 | struct EgoEntry *ego_entry = cls; | ||
631 | const struct GNUNET_GNSRECORD_Data *token_record; | ||
632 | const struct GNUNET_GNSRECORD_Data *token_metadata_record; | ||
633 | struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key; | ||
634 | struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key; | ||
635 | |||
636 | //There should be only a single record for a token under a label | ||
637 | if (2 != rd_count) | ||
638 | { | ||
639 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | ||
640 | return; | ||
641 | } | ||
642 | |||
643 | if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) | ||
644 | { | ||
645 | token_metadata_record = &rd[0]; | ||
646 | token_record = &rd[1]; | ||
647 | } | ||
648 | else | ||
649 | { | ||
650 | token_record = &rd[0]; | ||
651 | token_metadata_record = &rd[1]; | ||
652 | } | ||
653 | if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) | ||
654 | { | ||
655 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | ||
656 | return; | ||
657 | } | ||
658 | if (token_record->record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN) | ||
659 | { | ||
660 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | ||
661 | return; | ||
662 | } | ||
663 | |||
664 | //Get metadata and decrypt token | ||
665 | priv_key = (struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data; | ||
666 | ecdhe_privkey = *priv_key; | ||
667 | aud_key = (struct GNUNET_CRYPTO_EcdsaPublicKey *)&priv_key[1]; | ||
668 | scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
669 | |||
670 | token_parse2 (token_record->data, | ||
671 | &ecdhe_privkey, | ||
672 | aud_key, | ||
673 | &token); | ||
674 | |||
675 | label = GNUNET_strdup (lbl); | ||
676 | rd_exp = token_record->expiration_time; | ||
677 | |||
678 | GNUNET_SCHEDULER_add_now (&handle_token_update, | ||
679 | ego_entry); | ||
680 | } | ||
681 | |||
682 | |||
683 | static void | ||
684 | attribute_collect_error_cb (void *cls) | ||
685 | { | ||
686 | struct EgoEntry *ego_entry = cls; | ||
687 | |||
688 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
689 | ">>> Updating Attributes failed!\n"); | ||
690 | ego_entry->attributes_dirty = GNUNET_NO; | ||
691 | update_task = GNUNET_SCHEDULER_add_now (&update_identities, | ||
692 | ego_entry); | ||
693 | } | ||
694 | |||
695 | |||
696 | static void | ||
697 | attribute_collect_finished_cb (void *cls) | ||
698 | { | ||
699 | struct EgoEntry *ego_entry = cls; | ||
700 | |||
701 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
702 | ">>> Updating Attributes finished\n"); | ||
703 | ego_entry->attributes_dirty = GNUNET_NO; | ||
704 | update_task = GNUNET_SCHEDULER_add_now (&update_identities, | ||
705 | ego_entry); | ||
706 | } | ||
707 | |||
708 | |||
709 | /** | ||
710 | * | ||
711 | * Collect all ID_ATTR records for an identity and store them | ||
712 | * | ||
713 | * @param cls the identity entry | ||
714 | * @param zone the identity | ||
715 | * @param lbl the name of the record | ||
716 | * @param rd_count number of records | ||
717 | * @param rd record data | ||
718 | * | ||
719 | */ | ||
720 | static void | ||
721 | attribute_collect (void *cls, | ||
722 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | ||
723 | const char *lbl, | ||
724 | unsigned int rd_count, | ||
725 | const struct GNUNET_GNSRECORD_Data *rd) | ||
726 | { | ||
727 | struct EgoEntry *ego_entry = cls; | ||
728 | struct GNUNET_HashCode key; | ||
729 | struct TokenAttr *attr; | ||
730 | struct TokenAttrValue *val; | ||
731 | char *val_str; | ||
732 | int i; | ||
733 | |||
734 | if (0 == rd_count) | ||
735 | { | ||
736 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | ||
737 | return; | ||
738 | } | ||
739 | GNUNET_CRYPTO_hash (lbl, | ||
740 | strlen (lbl), | ||
741 | &key); | ||
742 | if (1 == rd_count) | ||
743 | { | ||
744 | if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) | ||
745 | { | ||
746 | val_str = GNUNET_GNSRECORD_value_to_string (rd->record_type, | ||
747 | rd->data, | ||
748 | rd->data_size); | ||
749 | attr = GNUNET_malloc (sizeof (struct TokenAttr)); | ||
750 | attr->name = GNUNET_strdup (lbl); | ||
751 | val = GNUNET_malloc (sizeof (struct TokenAttrValue)); | ||
752 | val->value = val_str; | ||
753 | GNUNET_CONTAINER_DLL_insert (attr->val_head, | ||
754 | attr->val_tail, | ||
755 | val); | ||
756 | GNUNET_assert (GNUNET_OK == | ||
757 | GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map, | ||
758 | &key, | ||
759 | attr, | ||
760 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
761 | } | ||
762 | |||
763 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | ||
764 | return; | ||
765 | } | ||
766 | |||
767 | attr = GNUNET_malloc (sizeof (struct TokenAttr)); | ||
768 | attr->name = GNUNET_strdup (lbl); | ||
769 | for (i = 0; i < rd_count; i++) | ||
770 | { | ||
771 | if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) | ||
772 | { | ||
773 | val_str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, | ||
774 | rd[i].data, | ||
775 | rd[i].data_size); | ||
776 | val = GNUNET_malloc (sizeof (struct TokenAttrValue)); | ||
777 | val->value = val_str; | ||
778 | GNUNET_CONTAINER_DLL_insert (attr->val_head, | ||
779 | attr->val_tail, | ||
780 | val); | ||
781 | } | ||
782 | } | ||
783 | GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map, | ||
784 | &key, | ||
785 | attr, | ||
786 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
787 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | ||
788 | } | ||
789 | |||
790 | /** | ||
791 | * | ||
792 | * Update identity information for ego. If attribute map is | ||
793 | * dirty, first update the attributes. | ||
794 | * | ||
795 | * @param cls the ego to update | ||
796 | */ | ||
797 | static void | ||
798 | update_identities(void *cls) | ||
799 | { | ||
800 | struct EgoEntry *next_ego = cls; | ||
801 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | ||
802 | |||
803 | update_task = NULL; | ||
804 | if (NULL == next_ego) | ||
805 | { | ||
806 | if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us) | ||
807 | min_rel_exp = MIN_WAIT_TIME; | ||
808 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
809 | ">>> Finished. Rescheduling in %"SCNu64"\n", | ||
810 | min_rel_exp.rel_value_us); | ||
811 | ns_it = NULL; | ||
812 | //finished -> reschedule | ||
813 | update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp, | ||
814 | &update_identities, | ||
815 | ego_head); | ||
816 | min_rel_exp.rel_value_us = 0; | ||
817 | return; | ||
818 | } | ||
819 | priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego); | ||
820 | if (GNUNET_YES == next_ego->attributes_dirty) | ||
821 | { | ||
822 | //Starting over. We must update the Attributes for they might have changed. | ||
823 | ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, | ||
824 | priv_key, | ||
825 | &attribute_collect_error_cb, | ||
826 | next_ego, | ||
827 | &attribute_collect, | ||
828 | next_ego, | ||
829 | &attribute_collect_finished_cb, | ||
830 | next_ego); | ||
831 | |||
832 | } | ||
833 | else | ||
834 | { | ||
835 | //Ego will be dirty next time | ||
836 | next_ego->attributes_dirty = GNUNET_YES; | ||
837 | ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, | ||
838 | priv_key, | ||
839 | &token_collect_error_cb, | ||
840 | next_ego, | ||
841 | &token_collect, | ||
842 | next_ego, | ||
843 | &token_collect_finished_cb, | ||
844 | next_ego); | ||
845 | } | ||
846 | } | ||
847 | |||
848 | |||
849 | /** | ||
850 | * Function called initially to start update task | ||
851 | */ | ||
852 | static void | ||
853 | init_cont () | ||
854 | { | ||
855 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, ">>> Starting Service\n"); | ||
856 | //Initially iterate all itenties and refresh all tokens | ||
857 | update_task = GNUNET_SCHEDULER_add_now (&update_identities, | ||
858 | ego_head); | ||
859 | } | ||
860 | |||
861 | |||
862 | /** | ||
863 | * Initial ego collection function. | ||
864 | * | ||
865 | * @param cls NULL | ||
866 | * @param ego ego | ||
867 | * @param ctx context | ||
868 | * @param identifier ego name | ||
869 | */ | ||
870 | static void | ||
871 | list_ego (void *cls, | ||
872 | struct GNUNET_IDENTITY_Ego *ego, | ||
873 | void **ctx, | ||
874 | const char *identifier) | ||
875 | { | ||
876 | struct EgoEntry *new_entry; | ||
877 | if ((NULL == ego) && (STATE_INIT == state)) | ||
878 | { | ||
879 | state = STATE_POST_INIT; | ||
880 | init_cont (); | ||
881 | return; | ||
882 | } | ||
883 | if (STATE_INIT == state) { | ||
884 | new_entry = GNUNET_malloc (sizeof (struct EgoEntry)); | ||
885 | new_entry->ego = ego; | ||
886 | new_entry->attr_map = GNUNET_CONTAINER_multihashmap_create (5, | ||
887 | GNUNET_NO); | ||
888 | new_entry->attributes_dirty = GNUNET_YES; | ||
889 | GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry); | ||
890 | } | ||
891 | } | ||
892 | |||
893 | /** | ||
894 | * Cleanup task | 312 | * Cleanup task |
895 | */ | 313 | */ |
896 | static void | 314 | static void |
897 | cleanup() | 315 | cleanup() |
898 | { | 316 | { |
899 | struct EgoEntry *ego_entry; | ||
900 | struct EgoEntry *ego_tmp; | ||
901 | |||
902 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 317 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
903 | "Cleaning up\n"); | 318 | "Cleaning up\n"); |
904 | if (NULL != stats) | 319 | if (NULL != stats) |
@@ -928,21 +343,6 @@ cleanup() | |||
928 | if (NULL != label) | 343 | if (NULL != label) |
929 | GNUNET_free (label); | 344 | GNUNET_free (label); |
930 | 345 | ||
931 | for (ego_entry = ego_head; | ||
932 | NULL != ego_entry;) | ||
933 | { | ||
934 | ego_tmp = ego_entry; | ||
935 | if (0 != GNUNET_CONTAINER_multihashmap_size (ego_tmp->attr_map)) | ||
936 | { | ||
937 | GNUNET_CONTAINER_multihashmap_iterate (ego_tmp->attr_map, | ||
938 | &clear_ego_attrs, | ||
939 | ego_tmp); | ||
940 | |||
941 | } | ||
942 | GNUNET_CONTAINER_multihashmap_destroy (ego_tmp->attr_map); | ||
943 | ego_entry = ego_entry->next; | ||
944 | GNUNET_free (ego_tmp); | ||
945 | } | ||
946 | } | 346 | } |
947 | 347 | ||
948 | /** | 348 | /** |
@@ -1023,7 +423,7 @@ cleanup_issue_handle (struct IssueHandle *handle) | |||
1023 | } | 423 | } |
1024 | 424 | ||
1025 | static void | 425 | static void |
1026 | store_token_issue_cont (void *cls, | 426 | store_record_issue_cont (void *cls, |
1027 | int32_t success, | 427 | int32_t success, |
1028 | const char *emsg) | 428 | const char *emsg) |
1029 | { | 429 | { |
@@ -1073,6 +473,82 @@ store_token_issue_cont (void *cls, | |||
1073 | GNUNET_free (token_str); | 473 | GNUNET_free (token_str); |
1074 | } | 474 | } |
1075 | 475 | ||
476 | static int | ||
477 | create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash, | ||
478 | struct GNUNET_CRYPTO_SymmetricSessionKey *skey, | ||
479 | struct GNUNET_CRYPTO_SymmetricInitializationVector *iv) | ||
480 | { | ||
481 | struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str; | ||
482 | |||
483 | GNUNET_CRYPTO_hash_to_enc (new_key_hash, | ||
484 | &new_key_hash_str); | ||
485 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str); | ||
486 | static const char ctx_key[] = "gnuid-aes-ctx-key"; | ||
487 | GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), | ||
488 | new_key_hash, sizeof (struct GNUNET_HashCode), | ||
489 | ctx_key, strlen (ctx_key), | ||
490 | NULL, 0); | ||
491 | static const char ctx_iv[] = "gnuid-aes-ctx-iv"; | ||
492 | GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector), | ||
493 | new_key_hash, sizeof (struct GNUNET_HashCode), | ||
494 | ctx_iv, strlen (ctx_iv), | ||
495 | NULL, 0); | ||
496 | return GNUNET_OK; | ||
497 | } | ||
498 | |||
499 | int | ||
500 | serialize_abe_keyinfo (const struct IssueHandle *handle, | ||
501 | const struct GNUNET_CRYPTO_AbeKey *rp_key, | ||
502 | struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey, | ||
503 | char **result) | ||
504 | { | ||
505 | char *enc_keyinfo; | ||
506 | char *serialized_key; | ||
507 | char *buf; | ||
508 | struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pubkey; | ||
509 | ssize_t size; | ||
510 | |||
511 | struct GNUNET_CRYPTO_SymmetricSessionKey skey; | ||
512 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
513 | struct GNUNET_HashCode new_key_hash; | ||
514 | ssize_t enc_size; | ||
515 | |||
516 | size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key, | ||
517 | &serialized_key); | ||
518 | buf = GNUNET_malloc (strlen (handle->scopes) + 1 + size); | ||
519 | GNUNET_memcpy (buf, | ||
520 | handle->scopes, | ||
521 | strlen (handle->scopes) + 1); | ||
522 | GNUNET_memcpy (buf + strlen (handle->scopes) + 1, | ||
523 | serialized_key, | ||
524 | size); | ||
525 | // ECDH keypair E = eG | ||
526 | *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create(); | ||
527 | GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey, | ||
528 | ecdh_pubkey); | ||
529 | enc_keyinfo = GNUNET_malloc (size); | ||
530 | // Derived key K = H(eB) | ||
531 | GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey, | ||
532 | &handle->aud_key, | ||
533 | &new_key_hash)); | ||
534 | create_sym_key_from_ecdh(&new_key_hash, &skey, &iv); | ||
535 | enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf, | ||
536 | size + strlen (handle->scopes) + 1, | ||
537 | &skey, &iv, | ||
538 | enc_keyinfo); | ||
539 | *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+ | ||
540 | enc_size); | ||
541 | GNUNET_memcpy (*result, | ||
542 | ecdh_pubkey, | ||
543 | sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); | ||
544 | GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey), | ||
545 | enc_keyinfo, | ||
546 | enc_size); | ||
547 | GNUNET_free (enc_keyinfo); | ||
548 | return GNUNET_OK; | ||
549 | } | ||
550 | |||
551 | |||
1076 | 552 | ||
1077 | /** | 553 | /** |
1078 | * Build a token and store it | 554 | * Build a token and store it |
@@ -1085,14 +561,18 @@ sign_and_return_token (void *cls) | |||
1085 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | 561 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; |
1086 | struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey; | 562 | struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey; |
1087 | struct IssueHandle *handle = cls; | 563 | struct IssueHandle *handle = cls; |
1088 | struct GNUNET_GNSRECORD_Data token_record[2]; | 564 | struct GNUNET_GNSRECORD_Data code_record[1]; |
565 | struct GNUNET_CRYPTO_AbeKey *rp_key; | ||
1089 | char *nonce_str; | 566 | char *nonce_str; |
1090 | char *enc_token_str; | 567 | char *code_record_data; |
1091 | char *token_metadata; | 568 | char **attrs; |
1092 | char* write_ptr; | 569 | char *scope; |
570 | char *scopes_tmp; | ||
571 | int attrs_len; | ||
572 | int i; | ||
1093 | uint64_t time; | 573 | uint64_t time; |
1094 | uint64_t exp_time; | 574 | uint64_t exp_time; |
1095 | size_t token_metadata_len; | 575 | size_t code_record_len; |
1096 | 576 | ||
1097 | //Remote nonce | 577 | //Remote nonce |
1098 | nonce_str = NULL; | 578 | nonce_str = NULL; |
@@ -1114,49 +594,39 @@ sign_and_return_token (void *cls) | |||
1114 | token_add_attr_int (handle->token, "exp", exp_time); | 594 | token_add_attr_int (handle->token, "exp", exp_time); |
1115 | token_add_attr (handle->token, "nonce", nonce_str); | 595 | token_add_attr (handle->token, "nonce", nonce_str); |
1116 | 596 | ||
1117 | //Token in a serialized encrypted format | 597 | //Create new ABE key for RP |
1118 | GNUNET_assert (token_serialize (handle->token, | 598 | attrs_len = (GNUNET_CONTAINER_multihashmap_size (handle->attr_map) + 1) * sizeof (char*); |
1119 | &handle->iss_key, | 599 | attrs = GNUNET_malloc (attrs_len); |
1120 | &ecdhe_privkey, | 600 | i = 0; |
1121 | &enc_token_str)); | 601 | scopes_tmp = GNUNET_strdup (handle->scopes); |
1122 | 602 | for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ",")) { | |
1123 | //Token record E,E_K (Token) | 603 | attrs[i] = scope; |
1124 | token_record[0].data = enc_token_str; | 604 | i++; |
1125 | token_record[0].data_size = strlen (enc_token_str) + 1; | 605 | } |
1126 | token_record[0].expiration_time = exp_time; | 606 | rp_key = GNUNET_CRYPTO_cpabe_create_key (handle->abe_key, |
1127 | token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN; | 607 | attrs); |
1128 | token_record[0].flags = GNUNET_GNSRECORD_RF_NONE; | 608 | code_record_len = serialize_abe_keyinfo (handle, |
1129 | 609 | rp_key, | |
1130 | 610 | &ecdhe_privkey, | |
1131 | token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey) | 611 | &code_record_data); |
1132 | + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) | 612 | code_record[0].data = code_record_data; |
1133 | + strlen (handle->scopes) + 1; //With 0-Terminator | 613 | code_record[0].data_size = code_record_len; |
1134 | token_metadata = GNUNET_malloc (token_metadata_len); | 614 | code_record[0].expiration_time = exp_time; |
1135 | write_ptr = token_metadata; | 615 | code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY; |
1136 | GNUNET_memcpy (token_metadata, ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); | 616 | code_record[0].flags = GNUNET_GNSRECORD_RF_NONE; |
1137 | write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); | 617 | |
1138 | GNUNET_memcpy (write_ptr, &handle->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | 618 | |
1139 | write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); | 619 | //Publish record |
1140 | GNUNET_memcpy (write_ptr, handle->scopes, strlen (handle->scopes) + 1); //with 0-Terminator; | ||
1141 | |||
1142 | token_record[1].data = token_metadata; | ||
1143 | token_record[1].data_size = token_metadata_len; | ||
1144 | token_record[1].expiration_time = exp_time; | ||
1145 | token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA; | ||
1146 | token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE; | ||
1147 | |||
1148 | //Persist token | ||
1149 | handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | 620 | handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, |
1150 | &handle->iss_key, | 621 | &handle->iss_key, |
1151 | handle->label, | 622 | handle->label, |
1152 | 2, | 623 | 1, |
1153 | token_record, | 624 | code_record, |
1154 | &store_token_issue_cont, | 625 | &store_record_issue_cont, |
1155 | handle); | 626 | handle); |
1156 | GNUNET_free (ecdhe_privkey); | 627 | GNUNET_free (ecdhe_privkey); |
1157 | GNUNET_free (nonce_str); | 628 | GNUNET_free (nonce_str); |
1158 | GNUNET_free (enc_token_str); | 629 | GNUNET_free (code_record_data); |
1159 | GNUNET_free (token_metadata); | ||
1160 | } | 630 | } |
1161 | 631 | ||
1162 | /** | 632 | /** |
@@ -1637,7 +1107,7 @@ run (void *cls, | |||
1637 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential"); | 1107 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential"); |
1638 | } | 1108 | } |
1639 | identity_handle = GNUNET_IDENTITY_connect (cfg, | 1109 | identity_handle = GNUNET_IDENTITY_connect (cfg, |
1640 | &list_ego, | 1110 | NULL, |
1641 | NULL); | 1111 | NULL); |
1642 | 1112 | ||
1643 | if (GNUNET_OK == | 1113 | if (GNUNET_OK == |
diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h index e33d52819..aa0c6721f 100644 --- a/src/include/gnunet_gnsrecord_lib.h +++ b/src/include/gnunet_gnsrecord_lib.h | |||
@@ -123,6 +123,10 @@ extern "C" | |||
123 | */ | 123 | */ |
124 | #define GNUNET_GNSRECORD_TYPE_ATTRIBUTE 65549 | 124 | #define GNUNET_GNSRECORD_TYPE_ATTRIBUTE 65549 |
125 | 125 | ||
126 | /** | ||
127 | * Record type for ABE records | ||
128 | */ | ||
129 | #define GNUNET_GNSRECORD_TYPE_ABE_KEY 65550 | ||
126 | 130 | ||
127 | /** | 131 | /** |
128 | * Flags that can be set for a record. | 132 | * Flags that can be set for a record. |