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 VerifiedAttributeEntry
137 struct VerifiedAttributeEntry *prev;
142 struct VerifiedAttributeEntry *next;
150 struct ParallelLookups;
152 struct ExchangeHandle
158 struct GNUNET_SERVICE_Client *client;
163 struct TokenTicket *ticket;
168 struct IdentityToken *token;
173 struct GNUNET_GNS_LookupRequest *lookup_request;
178 struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey;
181 * ParallelLookups DLL
183 struct ParallelLookup *parallel_lookups_head;
184 struct ParallelLookup *parallel_lookups_tail;
186 struct GNUNET_SCHEDULER_Task *kill_task;
187 struct GNUNET_CRYPTO_AbeKey *key;
200 struct ParallelLookup
202 struct ParallelLookup *next;
204 struct ParallelLookup *prev;
206 struct GNUNET_GNS_LookupRequest *lookup_request;
208 struct ExchangeHandle *handle;
217 struct GNUNET_SERVICE_Client *client;
222 struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key;
227 struct GNUNET_CRYPTO_EcdsaPublicKey iss_pkey;
232 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
235 * The issuer egos ABE master key
237 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
242 struct GNUNET_TIME_Absolute expiration;
252 struct VerifiedAttributeEntry *v_attr_head;
257 struct VerifiedAttributeEntry *v_attr_tail;
267 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
272 struct GNUNET_CREDENTIAL_Request *credential_request;
277 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
282 struct IdentityToken *token;
287 struct TokenTicket *ticket;
292 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
295 * The label the token is stored under
306 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
314 struct EgoEntry *next;
319 struct EgoEntry *prev;
324 struct GNUNET_IDENTITY_Ego *ego;
327 * Attribute map. Contains the attributes as json_t
329 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
339 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
343 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
347 if (NULL != timeout_task)
348 GNUNET_SCHEDULER_cancel (timeout_task);
349 if (NULL != update_task)
350 GNUNET_SCHEDULER_cancel (update_task);
351 if (NULL != identity_handle)
352 GNUNET_IDENTITY_disconnect (identity_handle);
353 if (NULL != gns_handle)
354 GNUNET_GNS_disconnect (gns_handle);
355 if (NULL != credential_handle)
356 GNUNET_CREDENTIAL_disconnect (credential_handle);
358 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
360 GNUNET_NAMESTORE_cancel (ns_qe);
361 if (NULL != ns_handle)
362 GNUNET_NAMESTORE_disconnect (ns_handle);
374 * @param tc task context
377 do_shutdown (void *cls)
379 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
380 "Shutting down...\n");
385 static struct GNUNET_MQ_Envelope*
386 create_exchange_result_message (const char* token,
388 uint64_t ticket_nonce,
391 struct GNUNET_MQ_Envelope *env;
392 struct ExchangeResultMessage *erm;
393 uint16_t token_len = strlen (token) + 1;
395 env = GNUNET_MQ_msg_extra (erm,
397 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT);
398 erm->ticket_nonce = htonl (ticket_nonce);
400 GNUNET_memcpy (&erm[1], token, token_len);
405 static struct GNUNET_MQ_Envelope*
406 create_issue_result_message (const char* label,
411 struct GNUNET_MQ_Envelope *env;
412 struct IssueResultMessage *irm;
416 GNUNET_asprintf (&tmp_str, "%s,%s,%s", label, ticket, token);
417 len = strlen (tmp_str) + 1;
418 env = GNUNET_MQ_msg_extra (irm,
420 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT);
422 GNUNET_memcpy (&irm[1], tmp_str, strlen (tmp_str) + 1);
423 GNUNET_free (tmp_str);
428 cleanup_issue_handle (struct IssueHandle *handle)
430 if (NULL != handle->attr_map)
431 GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map);
432 if (NULL != handle->scopes)
433 GNUNET_free (handle->scopes);
434 if (NULL != handle->token)
435 token_destroy (handle->token);
436 if (NULL != handle->ticket)
437 ticket_destroy (handle->ticket);
438 if (NULL != handle->label)
439 GNUNET_free (handle->label);
440 if (NULL != handle->ns_it)
441 GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
442 if (NULL != handle->credential_request)
443 GNUNET_CREDENTIAL_request_cancel (handle->credential_request);
444 GNUNET_free (handle);
448 store_record_issue_cont (void *cls,
452 struct IssueHandle *handle = cls;
453 struct GNUNET_MQ_Envelope *env;
457 handle->ns_qe = NULL;
458 if (GNUNET_SYSERR == success)
460 cleanup_issue_handle (handle);
461 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
463 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
466 if (GNUNET_OK != ticket_serialize (handle->ticket,
470 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
471 "Error serializing ticket\n");
472 cleanup_issue_handle (handle);
473 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
476 if (GNUNET_OK != token_to_string (handle->token,
480 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
481 "Error serializing token\n");
482 GNUNET_free (ticket_str);
483 cleanup_issue_handle (handle);
484 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
487 env = create_issue_result_message (handle->label,
491 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
493 cleanup_issue_handle (handle);
494 GNUNET_free (ticket_str);
495 GNUNET_free (token_str);
499 create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
500 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
501 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
503 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
505 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
507 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
508 static const char ctx_key[] = "gnuid-aes-ctx-key";
509 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
510 new_key_hash, sizeof (struct GNUNET_HashCode),
511 ctx_key, strlen (ctx_key),
513 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
514 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
515 new_key_hash, sizeof (struct GNUNET_HashCode),
516 ctx_iv, strlen (ctx_iv),
522 serialize_abe_keyinfo (const struct IssueHandle *handle,
523 const struct GNUNET_CRYPTO_AbeKey *rp_key,
524 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
528 char *serialized_key;
530 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pubkey;
533 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
534 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
535 struct GNUNET_HashCode new_key_hash;
538 size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key,
539 (void**)&serialized_key);
540 buf = GNUNET_malloc (strlen (handle->scopes) + 1 + size);
543 strlen (handle->scopes) + 1);
544 GNUNET_memcpy (buf + strlen (handle->scopes) + 1,
547 // ECDH keypair E = eG
549 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
550 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
552 enc_keyinfo = GNUNET_malloc (size);
553 // Derived key K = H(eB)
554 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
557 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
558 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
559 size + strlen (handle->scopes) + 1,
562 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
564 GNUNET_memcpy (*result,
566 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
567 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
570 GNUNET_free (enc_keyinfo);
575 cleanup_exchange_handle (struct ExchangeHandle *handle)
577 if (NULL != handle->ticket)
578 ticket_destroy (handle->ticket);
579 if (NULL != handle->token)
580 token_destroy (handle->token);
581 GNUNET_free (handle);
586 * Build a token and store it
588 * @param cls the IssueHandle
591 sign_and_return_token (void *cls)
593 struct ExchangeHandle *handle = cls;
594 struct GNUNET_MQ_Envelope *env;
599 time = GNUNET_TIME_absolute_get().abs_value_us;
600 exp_time = time + token_expiration_interval.rel_value_us;
602 token_add_attr_int (handle->token, "nbf", time);
603 token_add_attr_int (handle->token, "iat", time);
604 token_add_attr_int (handle->token, "exp", exp_time);
607 GNUNET_assert (GNUNET_OK == token_to_string (handle->token,
608 &handle->aud_privkey,
611 env = create_exchange_result_message (token_str,
613 handle->ticket->payload->nonce,
615 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
617 cleanup_exchange_handle (handle);
618 GNUNET_free (token_str);
623 * Build an ABE key and store it
625 * @param cls the IssueHandle
628 issue_ticket (void *cls)
630 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
631 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
632 struct IssueHandle *handle = cls;
633 struct GNUNET_GNSRECORD_Data code_record[1];
634 struct GNUNET_CRYPTO_AbeKey *rp_key;
636 char *code_record_data;
644 size_t code_record_len;
648 GNUNET_asprintf (&nonce_str, "%lu", handle->nonce);
649 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str);
651 GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key,
653 handle->ticket = ticket_create (handle->nonce,
658 time = GNUNET_TIME_absolute_get().abs_value_us;
659 exp_time = time + token_expiration_interval.rel_value_us;
661 token_add_attr_int (handle->token, "nbf", time);
662 token_add_attr_int (handle->token, "iat", time);
663 token_add_attr_int (handle->token, "exp", exp_time);
664 token_add_attr (handle->token, "nonce", nonce_str);
666 //Create new ABE key for RP
667 attrs_len = (GNUNET_CONTAINER_multihashmap_size (handle->attr_map) + 1) * sizeof (char*);
668 attrs = GNUNET_malloc (attrs_len);
670 scopes_tmp = GNUNET_strdup (handle->scopes);
671 for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ",")) {
675 rp_key = GNUNET_CRYPTO_cpabe_create_key (handle->abe_key,
677 code_record_len = serialize_abe_keyinfo (handle,
681 code_record[0].data = code_record_data;
682 code_record[0].data_size = code_record_len;
683 code_record[0].expiration_time = exp_time;
684 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
685 code_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
689 handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
694 &store_record_issue_cont,
696 GNUNET_free (ecdhe_privkey);
697 GNUNET_free (nonce_str);
698 GNUNET_free (code_record_data);
703 * @param cred the credential
704 * @return the resulting json, NULL if failed
707 credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
712 char attribute[cred->issuer_attribute_len + 1];
715 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
718 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
719 "Issuer in credential malformed\n");
722 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
725 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
726 "Subject in credential malformed\n");
727 GNUNET_free (issuer);
730 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
731 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
734 cred->issuer_attribute,
735 cred->issuer_attribute_len);
736 attribute[cred->issuer_attribute_len] = '\0';
737 cred_obj = json_object ();
738 json_object_set_new (cred_obj, "issuer", json_string (issuer));
739 json_object_set_new (cred_obj, "subject", json_string (subject));
740 json_object_set_new (cred_obj, "attribute", json_string (attribute));
741 json_object_set_new (cred_obj, "signature", json_string (signature));
742 json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
743 GNUNET_free (issuer);
744 GNUNET_free (subject);
745 GNUNET_free (signature);
751 handle_vattr_collection (void* cls,
752 unsigned int d_count,
753 struct GNUNET_CREDENTIAL_Delegation *dc,
754 unsigned int c_count,
755 struct GNUNET_CREDENTIAL_Credential *cred)
757 struct IssueHandle *handle = cls;
758 struct VerifiedAttributeEntry *vattr;
762 handle->credential_request = NULL;
766 GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
769 cred_array = json_array();
770 for (i=0;i<c_count;i++)
772 cred_json = credential_to_json (cred);
773 if (NULL == cred_json)
775 json_array_append (cred_array, cred_json);
776 token_add_attr_json (handle->token,
777 handle->v_attr_head->name,
780 json_decref (cred_array);
781 vattr = handle->v_attr_head;
783 GNUNET_CONTAINER_DLL_remove (handle->v_attr_head,
786 GNUNET_free (vattr->name);
789 if (NULL == handle->v_attr_head)
791 GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
794 handle->credential_request = GNUNET_CREDENTIAL_collect (credential_handle,
796 handle->v_attr_head->name,
798 &handle_vattr_collection,
805 attr_collect_error (void *cls)
807 struct IssueHandle *handle = cls;
809 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute Error!\n");
810 handle->ns_it = NULL;
811 GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
816 attr_collect_finished (void *cls)
818 struct IssueHandle *handle = cls;
820 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n");
821 handle->ns_it = NULL;
823 if (NULL == handle->v_attr_head)
825 GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
828 handle->credential_request = GNUNET_CREDENTIAL_collect (credential_handle,
830 handle->v_attr_head->name,
832 &handle_vattr_collection,
836 * Collect attributes for token
839 attr_collect (void *cls,
840 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
842 unsigned int rd_count,
843 const struct GNUNET_GNSRECORD_Data *rd)
845 struct IssueHandle *handle = cls;
848 struct GNUNET_HashCode key;
850 GNUNET_CRYPTO_hash (label,
855 ( (NULL != handle->attr_map) &&
856 (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map,
861 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
865 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", label);
869 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
871 data = GNUNET_GNSRECORD_value_to_string (rd->record_type,
874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
875 token_add_attr (handle->token,
880 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
885 for (; i < rd_count; i++)
887 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
889 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
892 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
893 token_add_attr (handle->token, label, data);
898 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
902 process_parallel_lookup (void *cls, uint32_t rd_count,
903 const struct GNUNET_GNSRECORD_Data *rd)
905 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
906 "Parallel lookup finished\n");
907 struct ParallelLookup *parallel_lookup = cls;
908 struct ExchangeHandle *handle = parallel_lookup->handle;
912 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
913 handle->parallel_lookups_tail,
915 GNUNET_free (parallel_lookup);
918 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
920 GNUNET_CRYPTO_cpabe_decrypt (rd->data,
924 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
925 token_add_attr (handle->token,
932 for (; i < rd_count; i++)
934 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
936 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
939 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
940 token_add_attr (handle->token, label, data);
945 if (NULL != handle->parallel_lookups_head)
946 return; //Wait for more
948 GNUNET_SCHEDULER_cancel (handle->kill_task);
949 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
953 abort_parallel_lookups (void *cls)
955 struct ExchangeHandle *handle = cls;
956 struct ParallelLookup *lu;
957 struct ParallelLookup *tmp;
959 for (lu = handle->parallel_lookups_head;
961 GNUNET_GNS_lookup_cancel (lu->lookup_request);
963 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
964 handle->parallel_lookups_tail,
969 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
974 process_lookup_result (void *cls, uint32_t rd_count,
975 const struct GNUNET_GNSRECORD_Data *rd)
977 struct ExchangeHandle *handle = cls;
978 struct GNUNET_HashCode new_key_hash;
979 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
980 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
981 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
982 struct ParallelLookup *parallel_lookup;
988 handle->lookup_request = NULL;
991 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
992 "Number of keys %d != 1.",
994 cleanup_exchange_handle (handle);
995 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1000 ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1002 buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1004 //Calculate symmetric key from ecdh parameters
1005 GNUNET_assert (GNUNET_OK ==
1006 GNUNET_CRYPTO_ecdsa_ecdh (&handle->aud_privkey,
1009 create_sym_key_from_ecdh (&new_key_hash,
1012 size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1013 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1018 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1019 "Decrypted bytes: %zd Expected bytes: %zd\n",
1020 size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1022 scopes = GNUNET_strdup (buf);
1024 handle->key = GNUNET_CRYPTO_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1025 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1026 - strlen (scopes) - 1);
1028 for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1030 GNUNET_asprintf (&lookup_query,
1033 GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->ticket->payload->identity_key));
1034 parallel_lookup = GNUNET_new (struct ParallelLookup);
1035 parallel_lookup->handle = handle;
1036 parallel_lookup->lookup_request
1037 = GNUNET_GNS_lookup (gns_handle,
1039 &handle->ticket->aud_key,
1040 GNUNET_GNSRECORD_TYPE_ID_ATTR,
1041 GNUNET_GNS_LO_LOCAL_MASTER,
1042 &process_parallel_lookup,
1044 GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1045 handle->parallel_lookups_tail,
1048 handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1049 &abort_parallel_lookups,
1054 * Checks a exchange message
1056 * @param cls client sending the message
1057 * @param xm message of type `struct ExchangeMessage`
1058 * @return #GNUNET_OK if @a xm is well-formed
1061 check_exchange_message (void *cls,
1062 const struct ExchangeMessage *xm)
1066 size = ntohs (xm->header.size);
1067 if (size <= sizeof (struct ExchangeMessage))
1070 return GNUNET_SYSERR;
1077 * Handler for exchange message
1080 * @param client who sent the message
1081 * @param message the message
1084 handle_exchange_message (void *cls,
1085 const struct ExchangeMessage *xm)
1087 struct ExchangeHandle *xchange_handle;
1088 struct GNUNET_SERVICE_Client *client = cls;
1092 ticket = (const char *) &xm[1];
1093 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1094 "Received EXCHANGE of `%s' from client\n",
1096 xchange_handle = GNUNET_malloc (sizeof (struct ExchangeHandle));
1097 xchange_handle->aud_privkey = xm->aud_privkey;
1098 xchange_handle->r_id = xm->id;
1099 if (GNUNET_SYSERR == ticket_parse (ticket,
1100 &xchange_handle->aud_privkey,
1101 &xchange_handle->ticket))
1103 GNUNET_free (xchange_handle);
1104 GNUNET_SERVICE_client_drop (client);
1107 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for ABE key under %s\n",
1108 xchange_handle->ticket->payload->label);
1109 GNUNET_asprintf (&lookup_query,
1111 xchange_handle->ticket->payload->label);
1112 GNUNET_SERVICE_client_continue (client);
1113 xchange_handle->client = client;
1114 xchange_handle->token = token_create (&xchange_handle->ticket->payload->identity_key,
1115 &xchange_handle->ticket->payload->identity_key);
1116 xchange_handle->lookup_request
1117 = GNUNET_GNS_lookup (gns_handle,
1119 &xchange_handle->ticket->payload->identity_key,
1120 GNUNET_GNSRECORD_TYPE_ABE_KEY,
1121 GNUNET_GNS_LO_LOCAL_MASTER,
1122 &process_lookup_result,
1124 GNUNET_free (lookup_query);
1129 * Checks an issue message
1131 * @param cls client sending the message
1132 * @param im message of type `struct IssueMessage`
1133 * @return #GNUNET_OK if @a im is well-formed
1136 check_issue_message(void *cls,
1137 const struct IssueMessage *im)
1141 size = ntohs (im->header.size);
1142 if (size <= sizeof (struct IssueMessage))
1145 return GNUNET_SYSERR;
1147 scopes = (char *) &im[1];
1148 if ('\0' != scopes[size - sizeof (struct IssueMessage) - 1])
1150 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1151 "Malformed scopes received!\n");
1153 return GNUNET_SYSERR;
1159 attr_collect_task (void *cls)
1161 struct IssueHandle *issue_handle = cls;
1163 issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1164 &issue_handle->iss_key,
1165 &attr_collect_error,
1169 &attr_collect_finished,
1174 store_bootstrap_cont (void *cls,
1178 if (GNUNET_SYSERR == success)
1180 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1181 "Failed to bootstrap ABE master %s\n",
1183 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1186 GNUNET_SCHEDULER_add_now (&attr_collect_task, cls);
1190 store_bootstrap_task (void *cls)
1192 struct IssueHandle *issue_handle = cls;
1193 struct GNUNET_GNSRECORD_Data rd[1];
1195 rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (issue_handle->abe_key,
1196 (void**)&rd[0].data);
1197 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
1198 rd[0].flags = GNUNET_GNSRECORD_RF_NONE | GNUNET_GNSRECORD_RF_PRIVATE;
1199 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1200 issue_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1201 &issue_handle->iss_key,
1205 &store_bootstrap_cont,
1210 abe_key_lookup_error (void *cls)
1212 GNUNET_SCHEDULER_add_now (&do_shutdown, cls);
1216 abe_key_lookup_result (void *cls,
1217 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1219 unsigned int rd_count,
1220 const struct GNUNET_GNSRECORD_Data *rd)
1222 struct IssueHandle *handle = cls;
1225 for (i=0;i<rd_count;i++) {
1226 if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
1228 handle->abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key ((void**)rd[i].data,
1230 GNUNET_SCHEDULER_add_now (&attr_collect_task, handle);
1234 //No ABE master found, bootstrapping...
1235 handle->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
1236 GNUNET_SCHEDULER_add_now (&store_bootstrap_task, handle);
1241 * Handler for issue message
1244 * @param client who sent the message
1245 * @param message the message
1248 handle_issue_message (void *cls,
1249 const struct IssueMessage *im)
1254 const char *v_attrs;
1256 struct GNUNET_HashCode key;
1257 struct IssueHandle *issue_handle;
1258 struct VerifiedAttributeEntry *vattr_entry;
1259 struct GNUNET_SERVICE_Client *client = cls;
1261 scopes = (const char *) &im[1];
1262 v_attrs = (const char *) &im[1] + ntohl(im->scope_len);
1263 issue_handle = GNUNET_malloc (sizeof (struct IssueHandle));
1264 issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
1266 scopes_tmp = GNUNET_strdup (scopes);
1268 for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ","))
1270 GNUNET_CRYPTO_hash (scope,
1273 GNUNET_CONTAINER_multihashmap_put (issue_handle->attr_map,
1276 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
1278 GNUNET_free (scopes_tmp);
1279 scopes_tmp = GNUNET_strdup (v_attrs);
1281 for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ","))
1283 vattr_entry = GNUNET_new (struct VerifiedAttributeEntry);
1284 vattr_entry->name = GNUNET_strdup (scope);
1285 GNUNET_CONTAINER_DLL_insert (issue_handle->v_attr_head,
1286 issue_handle->v_attr_tail,
1289 GNUNET_free (scopes_tmp);
1293 issue_handle->r_id = im->id;
1294 issue_handle->aud_key = im->aud_key;
1295 issue_handle->iss_key = im->iss_key;
1296 GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key,
1297 &issue_handle->iss_pkey);
1298 issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration);
1299 issue_handle->nonce = ntohl (im->nonce);
1300 GNUNET_SERVICE_client_continue (client);
1301 issue_handle->client = client;
1302 issue_handle->scopes = GNUNET_strdup (scopes);
1303 issue_handle->token = token_create (&issue_handle->iss_pkey,
1304 &issue_handle->aud_key);
1306 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1308 GNUNET_STRINGS_base64_encode ((char*)&rnd_key,
1310 &issue_handle->label);
1311 issue_handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
1312 &issue_handle->iss_key,
1314 &abe_key_lookup_error,
1316 &abe_key_lookup_result,
1322 * Main function that will be run
1324 * @param cls closure
1325 * @param args remaining command-line arguments
1326 * @param cfgfile name of the configuration file used (for saving, can be NULL)
1327 * @param c configuration
1331 const struct GNUNET_CONFIGURATION_Handle *c,
1332 struct GNUNET_SERVICE_Handle *server)
1336 stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
1338 //Connect to identity and namestore services
1339 ns_handle = GNUNET_NAMESTORE_connect (cfg);
1340 if (NULL == ns_handle)
1342 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
1345 gns_handle = GNUNET_GNS_connect (cfg);
1346 if (NULL == gns_handle)
1348 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1350 credential_handle = GNUNET_CREDENTIAL_connect (cfg);
1351 if (NULL == credential_handle)
1353 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
1355 identity_handle = GNUNET_IDENTITY_connect (cfg,
1360 GNUNET_CONFIGURATION_get_value_time (cfg,
1361 "identity-provider",
1362 "TOKEN_EXPIRATION_INTERVAL",
1363 &token_expiration_interval))
1365 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1366 "Time window for zone iteration: %s\n",
1367 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
1370 token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
1373 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1377 * Called whenever a client is disconnected.
1379 * @param cls closure
1380 * @param client identification of the client
1381 * @param app_ctx @a client
1384 client_disconnect_cb (void *cls,
1385 struct GNUNET_SERVICE_Client *client,
1388 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1389 "Client %p disconnected\n",
1395 * Add a client to our list of active clients.
1398 * @param client client to add
1399 * @param mq message queue for @a client
1400 * @return internal namestore client structure for this client
1403 client_connect_cb (void *cls,
1404 struct GNUNET_SERVICE_Client *client,
1405 struct GNUNET_MQ_Handle *mq)
1407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1408 "Client %p connected\n",
1416 * Define "main" method using service macro.
1419 ("identity-provider",
1420 GNUNET_SERVICE_OPTION_NONE,
1423 &client_disconnect_cb,
1425 GNUNET_MQ_hd_var_size (issue_message,
1426 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE,
1427 struct IssueMessage,
1429 GNUNET_MQ_hd_var_size (exchange_message,
1430 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE,
1431 struct ExchangeMessage,
1433 GNUNET_MQ_handler_end());
1434 /* end of gnunet-service-identity-provider.c */