2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V.
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.
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.
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.
21 * @author Martin Schanzenbach
22 * @file src/identity-provider/gnunet-service-identity-provider.c
23 * @brief Identity Token Service
27 #include "gnunet_util_lib.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_identity_service.h"
31 #include "gnunet_gnsrecord_lib.h"
32 #include "gnunet_namestore_service.h"
33 #include "gnunet_credential_service.h"
34 #include "gnunet_statistics_service.h"
35 #include "gnunet_gns_service.h"
36 #include "gnunet_signatures.h"
37 #include "identity_provider.h"
38 #include "identity_token.h"
47 * Normal operation state
49 #define STATE_POST_INIT 1
52 * Minimum interval between updates
54 #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
57 * Standard token expiration time
59 #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
64 static struct GNUNET_IDENTITY_Handle *identity_handle;
67 * Token expiration interval
69 static struct GNUNET_TIME_Relative token_expiration_interval;
74 static struct GNUNET_NAMESTORE_Handle *ns_handle;
79 static struct GNUNET_GNS_Handle *gns_handle;
84 static struct GNUNET_CREDENTIAL_Handle *credential_handle;
89 static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
94 static struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
99 static struct GNUNET_SCHEDULER_Task *timeout_task;
104 static struct GNUNET_SCHEDULER_Task *update_task;
108 * Currently processed token
110 static struct IdentityToken *token;
113 * Label for currently processed token
118 * Scopes for processed token
123 * Handle to the statistics service.
125 static struct GNUNET_STATISTICS_Handle *stats;
130 static const struct GNUNET_CONFIGURATION_Handle *cfg;
132 struct AttributeStoreHandle
138 struct GNUNET_SERVICE_Client *client;
143 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
148 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
151 * The issuer egos ABE master key
153 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
158 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
166 * The attribute value
168 char *attribute_value;
171 * Size of the attribute value
173 size_t attribute_value_len;
183 struct VerifiedAttributeEntry
188 struct VerifiedAttributeEntry *prev;
193 struct VerifiedAttributeEntry *next;
201 struct ParallelLookups;
203 struct ExchangeHandle
209 struct GNUNET_SERVICE_Client *client;
214 struct TokenTicket *ticket;
219 struct IdentityToken *token;
224 struct GNUNET_GNS_LookupRequest *lookup_request;
229 struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey;
232 * ParallelLookups DLL
234 struct ParallelLookup *parallel_lookups_head;
235 struct ParallelLookup *parallel_lookups_tail;
237 struct GNUNET_SCHEDULER_Task *kill_task;
238 struct GNUNET_CRYPTO_AbeKey *key;
251 struct ParallelLookup
253 struct ParallelLookup *next;
255 struct ParallelLookup *prev;
257 struct GNUNET_GNS_LookupRequest *lookup_request;
259 struct ExchangeHandle *handle;
270 struct GNUNET_SERVICE_Client *client;
275 struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key;
280 struct GNUNET_CRYPTO_EcdsaPublicKey iss_pkey;
285 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
288 * The issuer egos ABE master key
290 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
295 struct GNUNET_TIME_Absolute expiration;
305 struct VerifiedAttributeEntry *v_attr_head;
310 struct VerifiedAttributeEntry *v_attr_tail;
320 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
325 struct GNUNET_CREDENTIAL_Request *credential_request;
330 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
335 struct IdentityToken *token;
340 struct TokenTicket *ticket;
345 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
348 * The label the token is stored under
359 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
367 struct EgoEntry *next;
372 struct EgoEntry *prev;
377 struct GNUNET_IDENTITY_Ego *ego;
380 * Attribute map. Contains the attributes as json_t
382 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
396 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
400 if (NULL != timeout_task)
401 GNUNET_SCHEDULER_cancel (timeout_task);
402 if (NULL != update_task)
403 GNUNET_SCHEDULER_cancel (update_task);
404 if (NULL != identity_handle)
405 GNUNET_IDENTITY_disconnect (identity_handle);
406 if (NULL != gns_handle)
407 GNUNET_GNS_disconnect (gns_handle);
408 if (NULL != credential_handle)
409 GNUNET_CREDENTIAL_disconnect (credential_handle);
411 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
413 GNUNET_NAMESTORE_cancel (ns_qe);
414 if (NULL != ns_handle)
415 GNUNET_NAMESTORE_disconnect (ns_handle);
427 * @param tc task context
430 do_shutdown (void *cls)
432 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
433 "Shutting down...\n");
438 static struct GNUNET_MQ_Envelope*
439 create_exchange_result_message (const char* token,
441 uint64_t ticket_nonce,
444 struct GNUNET_MQ_Envelope *env;
445 struct ExchangeResultMessage *erm;
446 uint16_t token_len = strlen (token) + 1;
448 env = GNUNET_MQ_msg_extra (erm,
450 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT);
451 erm->ticket_nonce = htonl (ticket_nonce);
453 GNUNET_memcpy (&erm[1], token, token_len);
458 static struct GNUNET_MQ_Envelope*
459 create_issue_result_message (const char* label,
464 struct GNUNET_MQ_Envelope *env;
465 struct IssueResultMessage *irm;
469 GNUNET_asprintf (&tmp_str, "%s,%s,%s", label, ticket, token);
470 len = strlen (tmp_str) + 1;
471 env = GNUNET_MQ_msg_extra (irm,
473 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT);
475 GNUNET_memcpy (&irm[1], tmp_str, strlen (tmp_str) + 1);
476 GNUNET_free (tmp_str);
481 cleanup_issue_handle (struct IssueHandle *handle)
483 if (NULL != handle->attr_map)
484 GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map);
485 if (NULL != handle->scopes)
486 GNUNET_free (handle->scopes);
487 if (NULL != handle->token)
488 token_destroy (handle->token);
489 if (NULL != handle->ticket)
490 ticket_destroy (handle->ticket);
491 if (NULL != handle->label)
492 GNUNET_free (handle->label);
493 if (NULL != handle->ns_it)
494 GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
495 if (NULL != handle->credential_request)
496 GNUNET_CREDENTIAL_request_cancel (handle->credential_request);
497 GNUNET_free (handle);
501 store_record_issue_cont (void *cls,
505 struct IssueHandle *handle = cls;
506 struct GNUNET_MQ_Envelope *env;
510 handle->ns_qe = NULL;
511 if (GNUNET_SYSERR == success)
513 cleanup_issue_handle (handle);
514 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
516 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
519 if (GNUNET_OK != ticket_serialize (handle->ticket,
523 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
524 "Error serializing ticket\n");
525 cleanup_issue_handle (handle);
526 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
529 if (GNUNET_OK != token_to_string (handle->token,
533 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
534 "Error serializing token\n");
535 GNUNET_free (ticket_str);
536 cleanup_issue_handle (handle);
537 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
540 env = create_issue_result_message (handle->label,
544 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
546 cleanup_issue_handle (handle);
547 GNUNET_free (ticket_str);
548 GNUNET_free (token_str);
552 create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
553 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
554 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
556 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
558 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
560 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
561 static const char ctx_key[] = "gnuid-aes-ctx-key";
562 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
563 new_key_hash, sizeof (struct GNUNET_HashCode),
564 ctx_key, strlen (ctx_key),
566 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
567 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
568 new_key_hash, sizeof (struct GNUNET_HashCode),
569 ctx_iv, strlen (ctx_iv),
575 serialize_abe_keyinfo (const struct IssueHandle *handle,
576 const struct GNUNET_CRYPTO_AbeKey *rp_key,
577 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
581 char *serialized_key;
583 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
586 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
587 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
588 struct GNUNET_HashCode new_key_hash;
591 size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key,
592 (void**)&serialized_key);
593 buf = GNUNET_malloc (strlen (handle->scopes) + 1 + size);
596 strlen (handle->scopes) + 1);
597 GNUNET_memcpy (buf + strlen (handle->scopes) + 1,
600 // ECDH keypair E = eG
601 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
602 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
604 enc_keyinfo = GNUNET_malloc (size + strlen (handle->scopes) + 1);
605 // Derived key K = H(eB)
606 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
609 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
610 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
611 size + strlen (handle->scopes) + 1,
614 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
616 GNUNET_memcpy (*result,
618 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
619 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
622 GNUNET_free (enc_keyinfo);
623 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
627 cleanup_exchange_handle (struct ExchangeHandle *handle)
629 if (NULL != handle->ticket)
630 ticket_destroy (handle->ticket);
631 if (NULL != handle->token)
632 token_destroy (handle->token);
633 GNUNET_free (handle);
638 * Build a token and store it
640 * @param cls the IssueHandle
643 sign_and_return_token (void *cls)
645 struct ExchangeHandle *handle = cls;
646 struct GNUNET_MQ_Envelope *env;
651 time = GNUNET_TIME_absolute_get().abs_value_us;
652 exp_time = time + token_expiration_interval.rel_value_us;
654 token_add_attr_int (handle->token, "nbf", time);
655 token_add_attr_int (handle->token, "iat", time);
656 token_add_attr_int (handle->token, "exp", exp_time);
659 GNUNET_assert (GNUNET_OK == token_to_string (handle->token,
660 &handle->aud_privkey,
663 env = create_exchange_result_message (token_str,
665 handle->ticket->payload->nonce,
667 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
669 cleanup_exchange_handle (handle);
670 GNUNET_free (token_str);
675 * Build an ABE key and store it
677 * @param cls the IssueHandle
680 issue_ticket (void *cls)
682 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
683 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
684 struct IssueHandle *handle = cls;
685 struct GNUNET_GNSRECORD_Data code_record[1];
686 struct GNUNET_CRYPTO_AbeKey *rp_key;
688 char *code_record_data;
696 size_t code_record_len;
700 GNUNET_asprintf (&nonce_str, "%lu", handle->nonce);
701 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str);
703 GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key,
705 handle->ticket = ticket_create (handle->nonce,
710 time = GNUNET_TIME_absolute_get().abs_value_us;
711 exp_time = time + token_expiration_interval.rel_value_us;
713 token_add_attr_int (handle->token, "nbf", time);
714 token_add_attr_int (handle->token, "iat", time);
715 token_add_attr_int (handle->token, "exp", exp_time);
716 token_add_attr (handle->token, "nonce", nonce_str);
718 //Create new ABE key for RP
719 attrs_len = (GNUNET_CONTAINER_multihashmap_size (handle->attr_map) + 1) * sizeof (char*);
720 attrs = GNUNET_malloc (attrs_len);
722 scopes_tmp = GNUNET_strdup (handle->scopes);
723 for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ",")) {
727 rp_key = GNUNET_CRYPTO_cpabe_create_key (handle->abe_key,
729 code_record_len = serialize_abe_keyinfo (handle,
733 code_record[0].data = code_record_data;
734 code_record[0].data_size = code_record_len;
735 code_record[0].expiration_time = exp_time;
736 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
737 code_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
741 handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
746 &store_record_issue_cont,
748 GNUNET_free (ecdhe_privkey);
749 GNUNET_free (nonce_str);
750 GNUNET_free (code_record_data);
755 * @param cred the credential
756 * @return the resulting json, NULL if failed
759 credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
764 char attribute[cred->issuer_attribute_len + 1];
767 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
770 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
771 "Issuer in credential malformed\n");
774 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
777 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
778 "Subject in credential malformed\n");
779 GNUNET_free (issuer);
782 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
783 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
786 cred->issuer_attribute,
787 cred->issuer_attribute_len);
788 attribute[cred->issuer_attribute_len] = '\0';
789 cred_obj = json_object ();
790 json_object_set_new (cred_obj, "issuer", json_string (issuer));
791 json_object_set_new (cred_obj, "subject", json_string (subject));
792 json_object_set_new (cred_obj, "attribute", json_string (attribute));
793 json_object_set_new (cred_obj, "signature", json_string (signature));
794 json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
795 GNUNET_free (issuer);
796 GNUNET_free (subject);
797 GNUNET_free (signature);
803 handle_vattr_collection (void* cls,
804 unsigned int d_count,
805 struct GNUNET_CREDENTIAL_Delegation *dc,
806 unsigned int c_count,
807 struct GNUNET_CREDENTIAL_Credential *cred)
809 struct IssueHandle *handle = cls;
810 struct VerifiedAttributeEntry *vattr;
814 handle->credential_request = NULL;
818 GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
821 cred_array = json_array();
822 for (i=0;i<c_count;i++)
824 cred_json = credential_to_json (cred);
825 if (NULL == cred_json)
827 json_array_append (cred_array, cred_json);
828 token_add_attr_json (handle->token,
829 handle->v_attr_head->name,
832 json_decref (cred_array);
833 vattr = handle->v_attr_head;
835 GNUNET_CONTAINER_DLL_remove (handle->v_attr_head,
838 GNUNET_free (vattr->name);
841 if (NULL == handle->v_attr_head)
843 GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
846 handle->credential_request = GNUNET_CREDENTIAL_collect (credential_handle,
848 handle->v_attr_head->name,
850 &handle_vattr_collection,
857 attr_collect_error (void *cls)
859 struct IssueHandle *handle = cls;
861 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute Error!\n");
862 handle->ns_it = NULL;
863 GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
868 attr_collect_finished (void *cls)
870 struct IssueHandle *handle = cls;
872 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n");
873 handle->ns_it = NULL;
875 if (NULL == handle->v_attr_head)
877 GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
880 handle->credential_request = GNUNET_CREDENTIAL_collect (credential_handle,
882 handle->v_attr_head->name,
884 &handle_vattr_collection,
888 * Collect attributes for token
891 attr_collect (void *cls,
892 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
894 unsigned int rd_count,
895 const struct GNUNET_GNSRECORD_Data *rd)
897 struct IssueHandle *handle = cls;
900 struct GNUNET_HashCode key;
902 GNUNET_CRYPTO_hash (label,
907 ( (NULL != handle->attr_map) &&
908 (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map,
913 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
917 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", label);
921 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
923 data = GNUNET_GNSRECORD_value_to_string (rd->record_type,
926 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
927 token_add_attr (handle->token,
932 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
937 for (; i < rd_count; i++)
939 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
941 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
944 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
945 token_add_attr (handle->token, label, data);
950 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
954 process_parallel_lookup (void *cls, uint32_t rd_count,
955 const struct GNUNET_GNSRECORD_Data *rd)
957 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
958 "Parallel lookup finished (count=%u)\n", rd_count);
959 struct ParallelLookup *parallel_lookup = cls;
960 struct ExchangeHandle *handle = parallel_lookup->handle;
964 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
965 handle->parallel_lookups_tail,
967 GNUNET_free (parallel_lookup);
970 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
972 GNUNET_CRYPTO_cpabe_decrypt (rd->data,
976 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Adding value: %s\n", data);
977 token_add_attr (handle->token,
978 parallel_lookup->label,
984 for (; i < rd_count; i++)
986 if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
988 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
991 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Adding value: %s\n", data);
992 token_add_attr (handle->token, parallel_lookup->label, data);
997 if (NULL != handle->parallel_lookups_head)
998 return; //Wait for more
1000 GNUNET_SCHEDULER_cancel (handle->kill_task);
1001 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
1005 abort_parallel_lookups (void *cls)
1007 struct ExchangeHandle *handle = cls;
1008 struct ParallelLookup *lu;
1009 struct ParallelLookup *tmp;
1011 for (lu = handle->parallel_lookups_head;
1013 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1014 GNUNET_free (lu->label);
1016 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1017 handle->parallel_lookups_tail,
1022 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
1027 process_lookup_result (void *cls, uint32_t rd_count,
1028 const struct GNUNET_GNSRECORD_Data *rd)
1030 struct ExchangeHandle *handle = cls;
1031 struct GNUNET_HashCode new_key_hash;
1032 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1033 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1034 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1035 struct ParallelLookup *parallel_lookup;
1041 handle->lookup_request = NULL;
1044 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1045 "Number of keys %d != 1.",
1047 cleanup_exchange_handle (handle);
1048 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1053 ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1055 buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1057 //Calculate symmetric key from ecdh parameters
1058 GNUNET_assert (GNUNET_OK ==
1059 GNUNET_CRYPTO_ecdsa_ecdh (&handle->aud_privkey,
1062 create_sym_key_from_ecdh (&new_key_hash,
1065 size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1066 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1071 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1072 "Decrypted bytes: %zd Expected bytes: %zd\n",
1073 size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1075 scopes = GNUNET_strdup (buf);
1076 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1077 "Scopes %s\n", scopes);
1078 handle->key = GNUNET_CRYPTO_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1079 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1080 - strlen (scopes) - 1);
1082 for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1084 GNUNET_asprintf (&lookup_query,
1087 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1088 "Looking up %s\n", lookup_query);
1089 parallel_lookup = GNUNET_new (struct ParallelLookup);
1090 parallel_lookup->handle = handle;
1091 parallel_lookup->label = GNUNET_strdup (scope);
1092 parallel_lookup->lookup_request
1093 = GNUNET_GNS_lookup (gns_handle,
1095 &handle->ticket->payload->identity_key,
1096 GNUNET_GNSRECORD_TYPE_ID_ATTR,
1097 GNUNET_GNS_LO_LOCAL_MASTER,
1098 &process_parallel_lookup,
1100 GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1101 handle->parallel_lookups_tail,
1104 handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1105 &abort_parallel_lookups,
1110 * Checks a exchange message
1112 * @param cls client sending the message
1113 * @param xm message of type `struct ExchangeMessage`
1114 * @return #GNUNET_OK if @a xm is well-formed
1117 check_exchange_message (void *cls,
1118 const struct ExchangeMessage *xm)
1122 size = ntohs (xm->header.size);
1123 if (size <= sizeof (struct ExchangeMessage))
1126 return GNUNET_SYSERR;
1133 * Handler for exchange message
1136 * @param client who sent the message
1137 * @param message the message
1140 handle_exchange_message (void *cls,
1141 const struct ExchangeMessage *xm)
1143 struct ExchangeHandle *xchange_handle;
1144 struct GNUNET_SERVICE_Client *client = cls;
1148 ticket = (const char *) &xm[1];
1149 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1150 "Received EXCHANGE of `%s' from client\n",
1152 xchange_handle = GNUNET_malloc (sizeof (struct ExchangeHandle));
1153 xchange_handle->aud_privkey = xm->aud_privkey;
1154 xchange_handle->r_id = xm->id;
1155 if (GNUNET_SYSERR == ticket_parse (ticket,
1156 &xchange_handle->aud_privkey,
1157 &xchange_handle->ticket))
1159 GNUNET_free (xchange_handle);
1160 GNUNET_SERVICE_client_drop (client);
1163 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for ABE key under %s\n",
1164 xchange_handle->ticket->payload->label);
1165 GNUNET_asprintf (&lookup_query,
1167 xchange_handle->ticket->payload->label);
1168 GNUNET_SERVICE_client_continue (client);
1169 xchange_handle->client = client;
1170 xchange_handle->token = token_create (&xchange_handle->ticket->payload->identity_key,
1171 &xchange_handle->ticket->payload->identity_key);
1172 xchange_handle->lookup_request
1173 = GNUNET_GNS_lookup (gns_handle,
1175 &xchange_handle->ticket->payload->identity_key,
1176 GNUNET_GNSRECORD_TYPE_ABE_KEY,
1177 GNUNET_GNS_LO_LOCAL_MASTER,
1178 &process_lookup_result,
1180 GNUNET_free (lookup_query);
1185 * Checks an issue message
1187 * @param cls client sending the message
1188 * @param im message of type `struct IssueMessage`
1189 * @return #GNUNET_OK if @a im is well-formed
1192 check_issue_message(void *cls,
1193 const struct IssueMessage *im)
1197 size = ntohs (im->header.size);
1198 if (size <= sizeof (struct IssueMessage))
1201 return GNUNET_SYSERR;
1203 scopes = (char *) &im[1];
1204 if ('\0' != scopes[size - sizeof (struct IssueMessage) - 1])
1206 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1207 "Malformed scopes received!\n");
1209 return GNUNET_SYSERR;
1215 attr_collect_task (void *cls)
1217 struct IssueHandle *issue_handle = cls;
1219 issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1220 &issue_handle->iss_key,
1221 &attr_collect_error,
1225 &attr_collect_finished,
1232 abe_key_lookup_error (void *cls)
1234 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1235 "Error looking for ABE master!\n");
1236 GNUNET_SCHEDULER_add_now (&do_shutdown, cls);
1240 abe_key_lookup_result (void *cls,
1241 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1243 unsigned int rd_count,
1244 const struct GNUNET_GNSRECORD_Data *rd)
1246 struct IssueHandle *handle = cls;
1249 for (i=0;i<rd_count;i++) {
1250 if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
1252 handle->abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key ((void**)rd[i].data,
1254 GNUNET_SCHEDULER_add_now (&attr_collect_task, handle);
1257 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1258 "No ABE master found!\n");
1259 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1265 * Handler for issue message
1268 * @param client who sent the message
1269 * @param message the message
1272 handle_issue_message (void *cls,
1273 const struct IssueMessage *im)
1279 struct GNUNET_HashCode key;
1280 struct IssueHandle *issue_handle;
1281 struct GNUNET_SERVICE_Client *client = cls;
1283 scopes = (const char *) &im[1];
1284 //v_attrs = (const char *) &im[1] + ntohl(im->scope_len);
1285 issue_handle = GNUNET_malloc (sizeof (struct IssueHandle));
1286 issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
1288 scopes_tmp = GNUNET_strdup (scopes);
1290 for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ","))
1292 GNUNET_CRYPTO_hash (scope,
1295 GNUNET_CONTAINER_multihashmap_put (issue_handle->attr_map,
1298 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
1300 GNUNET_free (scopes_tmp);
1301 /*scopes_tmp = GNUNET_strdup (v_attrs);
1303 for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ","))
1305 vattr_entry = GNUNET_new (struct VerifiedAttributeEntry);
1306 vattr_entry->name = GNUNET_strdup (scope);
1307 GNUNET_CONTAINER_DLL_insert (issue_handle->v_attr_head,
1308 issue_handle->v_attr_tail,
1311 GNUNET_free (scopes_tmp);*/
1315 issue_handle->r_id = im->id;
1316 issue_handle->aud_key = im->aud_key;
1317 issue_handle->iss_key = im->iss_key;
1318 GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key,
1319 &issue_handle->iss_pkey);
1320 issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration);
1321 issue_handle->nonce = ntohl (im->nonce);
1322 GNUNET_SERVICE_client_continue (client);
1323 issue_handle->client = client;
1324 issue_handle->scopes = GNUNET_strdup (scopes);
1325 issue_handle->token = token_create (&issue_handle->iss_pkey,
1326 &issue_handle->aud_key);
1328 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1330 GNUNET_STRINGS_base64_encode ((char*)&rnd_key,
1332 &issue_handle->label);
1333 issue_handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
1334 &issue_handle->iss_key,
1336 &abe_key_lookup_error,
1338 &abe_key_lookup_result,
1343 cleanup_as_handle (struct AttributeStoreHandle *handle)
1345 if (NULL != handle->name)
1346 GNUNET_free (handle->name);
1347 if (NULL != handle->attribute_value)
1348 GNUNET_free (handle->attribute_value);
1349 GNUNET_free (handle);
1355 attr_store_cont (void *cls,
1359 struct AttributeStoreHandle *as_handle = cls;
1360 struct GNUNET_MQ_Envelope *env;
1361 struct AttributeStoreResponseMessage *acr_msg;
1363 if (GNUNET_SYSERR == success)
1365 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1366 "Failed to store attribute %s\n",
1368 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1372 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1373 "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1374 env = GNUNET_MQ_msg (acr_msg,
1375 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
1376 acr_msg->id = htonl (as_handle->r_id);
1377 acr_msg->op_result = htonl (GNUNET_OK);
1378 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(as_handle->client),
1380 cleanup_as_handle (as_handle);
1384 attr_store_task (void *cls)
1386 struct AttributeStoreHandle *as_handle = cls;
1387 struct GNUNET_GNSRECORD_Data rd[1];
1390 * Encrypt the attribute value and store in namestore
1392 rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (as_handle->attribute_value,
1393 as_handle->attribute_value_len,
1394 as_handle->name, //Policy
1396 (void**)&rd[0].data);
1397 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1398 rd[0].flags = GNUNET_GNSRECORD_RF_NONE;
1399 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1400 as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1401 &as_handle->identity,
1411 store_bootstrap_cont (void *cls,
1415 if (GNUNET_SYSERR == success)
1417 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1418 "Failed to bootstrap ABE master %s\n",
1420 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1423 GNUNET_SCHEDULER_add_now (&attr_store_task, cls);
1427 store_bootstrap_task (void *cls)
1429 struct AttributeStoreHandle *as_handle = cls;
1430 struct GNUNET_GNSRECORD_Data rd[1];
1432 rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (as_handle->abe_key,
1433 (void**)&rd[0].data);
1434 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
1435 rd[0].flags = GNUNET_GNSRECORD_RF_NONE | GNUNET_GNSRECORD_RF_PRIVATE;
1436 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1437 as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1438 &as_handle->identity,
1442 &store_bootstrap_cont,
1447 store_cont_abe_error (void *cls)
1449 GNUNET_SCHEDULER_add_now (&do_shutdown, cls);
1453 store_cont_abe_result (void *cls,
1454 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1456 unsigned int rd_count,
1457 const struct GNUNET_GNSRECORD_Data *rd)
1459 struct AttributeStoreHandle *handle = cls;
1462 for (i=0;i<rd_count;i++) {
1463 if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
1465 handle->abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key ((void**)rd[i].data,
1467 GNUNET_SCHEDULER_add_now (&attr_collect_task, handle);
1471 //No ABE master found, bootstrapping...
1472 handle->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
1473 GNUNET_SCHEDULER_add_now (&store_bootstrap_task, handle);
1478 * Checks a store message
1480 * @param cls client sending the message
1481 * @param sam message of type `struct AttributeStoreMessage`
1482 * @return #GNUNET_OK if @a im is well-formed
1485 check_attribute_store_message(void *cls,
1486 const struct AttributeStoreMessage *sam)
1491 size = ntohs (sam->header.size);
1492 if (size <= sizeof (struct AttributeStoreMessage))
1495 return GNUNET_SYSERR;
1497 name_len = ntohs (sam->name_len);
1500 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1501 "Malformed store message received!\n");
1503 return GNUNET_SYSERR;
1510 * Handler for store message
1513 * @param client who sent the message
1514 * @param message the message
1517 handle_attribute_store_message (void *cls,
1518 const struct AttributeStoreMessage *sam)
1520 struct AttributeStoreHandle *as_handle;
1521 struct GNUNET_SERVICE_Client *client = cls;
1524 char *attribute_value;
1526 name_len = ntohs (sam->name_len);
1527 data_len = ntohs (sam->attr_value_len);
1529 as_handle = GNUNET_new (struct AttributeStoreHandle);
1530 as_handle->name = GNUNET_strndup ((char*)&sam[1], name_len);
1531 attribute_value = (char*)&sam[1] + name_len;
1533 as_handle->r_id = sam->id;
1534 as_handle->identity = sam->identity;
1535 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1536 &as_handle->identity_pkey);
1537 as_handle->attribute_value = GNUNET_malloc (data_len);
1538 GNUNET_memcpy (as_handle->attribute_value,
1541 as_handle->attribute_value_len = data_len;
1543 GNUNET_SERVICE_client_continue (client);
1544 as_handle->client = client;
1545 as_handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
1546 &as_handle->identity,
1548 &store_cont_abe_error,
1550 &store_cont_abe_result,
1556 * Main function that will be run
1558 * @param cls closure
1559 * @param args remaining command-line arguments
1560 * @param cfgfile name of the configuration file used (for saving, can be NULL)
1561 * @param c configuration
1565 const struct GNUNET_CONFIGURATION_Handle *c,
1566 struct GNUNET_SERVICE_Handle *server)
1570 stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
1572 //Connect to identity and namestore services
1573 ns_handle = GNUNET_NAMESTORE_connect (cfg);
1574 if (NULL == ns_handle)
1576 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
1579 gns_handle = GNUNET_GNS_connect (cfg);
1580 if (NULL == gns_handle)
1582 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1584 credential_handle = GNUNET_CREDENTIAL_connect (cfg);
1585 if (NULL == credential_handle)
1587 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
1589 identity_handle = GNUNET_IDENTITY_connect (cfg,
1594 GNUNET_CONFIGURATION_get_value_time (cfg,
1595 "identity-provider",
1596 "TOKEN_EXPIRATION_INTERVAL",
1597 &token_expiration_interval))
1599 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1600 "Time window for zone iteration: %s\n",
1601 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
1604 token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
1607 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1611 * Called whenever a client is disconnected.
1613 * @param cls closure
1614 * @param client identification of the client
1615 * @param app_ctx @a client
1618 client_disconnect_cb (void *cls,
1619 struct GNUNET_SERVICE_Client *client,
1622 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1623 "Client %p disconnected\n",
1629 * Add a client to our list of active clients.
1632 * @param client client to add
1633 * @param mq message queue for @a client
1634 * @return internal namestore client structure for this client
1637 client_connect_cb (void *cls,
1638 struct GNUNET_SERVICE_Client *client,
1639 struct GNUNET_MQ_Handle *mq)
1641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1642 "Client %p connected\n",
1650 * Define "main" method using service macro.
1653 ("identity-provider",
1654 GNUNET_SERVICE_OPTION_NONE,
1657 &client_disconnect_cb,
1659 GNUNET_MQ_hd_var_size (issue_message,
1660 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE,
1661 struct IssueMessage,
1663 GNUNET_MQ_hd_var_size (exchange_message,
1664 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE,
1665 struct ExchangeMessage,
1667 GNUNET_MQ_hd_var_size (attribute_store_message,
1668 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
1669 struct AttributeStoreMessage,
1671 GNUNET_MQ_handler_end());
1672 /* end of gnunet-service-identity-provider.c */