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;
219 struct GNUNET_SERVICE_Client *client;
224 struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key;
229 struct GNUNET_CRYPTO_EcdsaPublicKey iss_pkey;
234 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
237 * The issuer egos ABE master key
239 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
244 struct GNUNET_TIME_Absolute expiration;
254 struct VerifiedAttributeEntry *v_attr_head;
259 struct VerifiedAttributeEntry *v_attr_tail;
269 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
274 struct GNUNET_CREDENTIAL_Request *credential_request;
279 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
284 struct IdentityToken *token;
289 struct TokenTicket *ticket;
294 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
297 * The label the token is stored under
308 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
316 struct EgoEntry *next;
321 struct EgoEntry *prev;
326 struct GNUNET_IDENTITY_Ego *ego;
329 * Attribute map. Contains the attributes as json_t
331 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
341 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
345 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
349 if (NULL != timeout_task)
350 GNUNET_SCHEDULER_cancel (timeout_task);
351 if (NULL != update_task)
352 GNUNET_SCHEDULER_cancel (update_task);
353 if (NULL != identity_handle)
354 GNUNET_IDENTITY_disconnect (identity_handle);
355 if (NULL != gns_handle)
356 GNUNET_GNS_disconnect (gns_handle);
357 if (NULL != credential_handle)
358 GNUNET_CREDENTIAL_disconnect (credential_handle);
360 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
362 GNUNET_NAMESTORE_cancel (ns_qe);
363 if (NULL != ns_handle)
364 GNUNET_NAMESTORE_disconnect (ns_handle);
376 * @param tc task context
379 do_shutdown (void *cls)
381 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
382 "Shutting down...\n");
387 static struct GNUNET_MQ_Envelope*
388 create_exchange_result_message (const char* token,
390 uint64_t ticket_nonce,
393 struct GNUNET_MQ_Envelope *env;
394 struct ExchangeResultMessage *erm;
395 uint16_t token_len = strlen (token) + 1;
397 env = GNUNET_MQ_msg_extra (erm,
399 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT);
400 erm->ticket_nonce = htonl (ticket_nonce);
402 GNUNET_memcpy (&erm[1], token, token_len);
407 static struct GNUNET_MQ_Envelope*
408 create_issue_result_message (const char* label,
413 struct GNUNET_MQ_Envelope *env;
414 struct IssueResultMessage *irm;
418 GNUNET_asprintf (&tmp_str, "%s,%s,%s", label, ticket, token);
419 len = strlen (tmp_str) + 1;
420 env = GNUNET_MQ_msg_extra (irm,
422 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT);
424 GNUNET_memcpy (&irm[1], tmp_str, strlen (tmp_str) + 1);
425 GNUNET_free (tmp_str);
430 cleanup_issue_handle (struct IssueHandle *handle)
432 if (NULL != handle->attr_map)
433 GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map);
434 if (NULL != handle->scopes)
435 GNUNET_free (handle->scopes);
436 if (NULL != handle->token)
437 token_destroy (handle->token);
438 if (NULL != handle->ticket)
439 ticket_destroy (handle->ticket);
440 if (NULL != handle->label)
441 GNUNET_free (handle->label);
442 if (NULL != handle->ns_it)
443 GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
444 if (NULL != handle->credential_request)
445 GNUNET_CREDENTIAL_request_cancel (handle->credential_request);
446 GNUNET_free (handle);
450 store_record_issue_cont (void *cls,
454 struct IssueHandle *handle = cls;
455 struct GNUNET_MQ_Envelope *env;
459 handle->ns_qe = NULL;
460 if (GNUNET_SYSERR == success)
462 cleanup_issue_handle (handle);
463 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
465 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
468 if (GNUNET_OK != ticket_serialize (handle->ticket,
472 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
473 "Error serializing ticket\n");
474 cleanup_issue_handle (handle);
475 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
478 if (GNUNET_OK != token_to_string (handle->token,
482 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
483 "Error serializing token\n");
484 GNUNET_free (ticket_str);
485 cleanup_issue_handle (handle);
486 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
489 env = create_issue_result_message (handle->label,
493 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
495 cleanup_issue_handle (handle);
496 GNUNET_free (ticket_str);
497 GNUNET_free (token_str);
501 create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
502 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
503 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
505 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
507 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
509 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
510 static const char ctx_key[] = "gnuid-aes-ctx-key";
511 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
512 new_key_hash, sizeof (struct GNUNET_HashCode),
513 ctx_key, strlen (ctx_key),
515 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
516 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
517 new_key_hash, sizeof (struct GNUNET_HashCode),
518 ctx_iv, strlen (ctx_iv),
524 serialize_abe_keyinfo (const struct IssueHandle *handle,
525 const struct GNUNET_CRYPTO_AbeKey *rp_key,
526 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
530 char *serialized_key;
532 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
535 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
536 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
537 struct GNUNET_HashCode new_key_hash;
540 size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key,
541 (void**)&serialized_key);
542 buf = GNUNET_malloc (strlen (handle->scopes) + 1 + size);
545 strlen (handle->scopes) + 1);
546 GNUNET_memcpy (buf + strlen (handle->scopes) + 1,
549 // ECDH keypair E = eG
550 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
551 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
553 enc_keyinfo = GNUNET_malloc (size + strlen (handle->scopes) + 1);
554 // Derived key K = H(eB)
555 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
558 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
559 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
560 size + strlen (handle->scopes) + 1,
563 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
565 GNUNET_memcpy (*result,
567 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
568 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
571 GNUNET_free (enc_keyinfo);
572 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
576 cleanup_exchange_handle (struct ExchangeHandle *handle)
578 if (NULL != handle->ticket)
579 ticket_destroy (handle->ticket);
580 if (NULL != handle->token)
581 token_destroy (handle->token);
582 GNUNET_free (handle);
587 * Build a token and store it
589 * @param cls the IssueHandle
592 sign_and_return_token (void *cls)
594 struct ExchangeHandle *handle = cls;
595 struct GNUNET_MQ_Envelope *env;
600 time = GNUNET_TIME_absolute_get().abs_value_us;
601 exp_time = time + token_expiration_interval.rel_value_us;
603 token_add_attr_int (handle->token, "nbf", time);
604 token_add_attr_int (handle->token, "iat", time);
605 token_add_attr_int (handle->token, "exp", exp_time);
608 GNUNET_assert (GNUNET_OK == token_to_string (handle->token,
609 &handle->aud_privkey,
612 env = create_exchange_result_message (token_str,
614 handle->ticket->payload->nonce,
616 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
618 cleanup_exchange_handle (handle);
619 GNUNET_free (token_str);
624 * Build an ABE key and store it
626 * @param cls the IssueHandle
629 issue_ticket (void *cls)
631 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
632 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
633 struct IssueHandle *handle = cls;
634 struct GNUNET_GNSRECORD_Data code_record[1];
635 struct GNUNET_CRYPTO_AbeKey *rp_key;
637 char *code_record_data;
645 size_t code_record_len;
649 GNUNET_asprintf (&nonce_str, "%lu", handle->nonce);
650 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str);
652 GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key,
654 handle->ticket = ticket_create (handle->nonce,
659 time = GNUNET_TIME_absolute_get().abs_value_us;
660 exp_time = time + token_expiration_interval.rel_value_us;
662 token_add_attr_int (handle->token, "nbf", time);
663 token_add_attr_int (handle->token, "iat", time);
664 token_add_attr_int (handle->token, "exp", exp_time);
665 token_add_attr (handle->token, "nonce", nonce_str);
667 //Create new ABE key for RP
668 attrs_len = (GNUNET_CONTAINER_multihashmap_size (handle->attr_map) + 1) * sizeof (char*);
669 attrs = GNUNET_malloc (attrs_len);
671 scopes_tmp = GNUNET_strdup (handle->scopes);
672 for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ",")) {
676 rp_key = GNUNET_CRYPTO_cpabe_create_key (handle->abe_key,
678 code_record_len = serialize_abe_keyinfo (handle,
682 code_record[0].data = code_record_data;
683 code_record[0].data_size = code_record_len;
684 code_record[0].expiration_time = exp_time;
685 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
686 code_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
690 handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
695 &store_record_issue_cont,
697 GNUNET_free (ecdhe_privkey);
698 GNUNET_free (nonce_str);
699 GNUNET_free (code_record_data);
704 * @param cred the credential
705 * @return the resulting json, NULL if failed
708 credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
713 char attribute[cred->issuer_attribute_len + 1];
716 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
719 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
720 "Issuer in credential malformed\n");
723 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
726 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
727 "Subject in credential malformed\n");
728 GNUNET_free (issuer);
731 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
732 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
735 cred->issuer_attribute,
736 cred->issuer_attribute_len);
737 attribute[cred->issuer_attribute_len] = '\0';
738 cred_obj = json_object ();
739 json_object_set_new (cred_obj, "issuer", json_string (issuer));
740 json_object_set_new (cred_obj, "subject", json_string (subject));
741 json_object_set_new (cred_obj, "attribute", json_string (attribute));
742 json_object_set_new (cred_obj, "signature", json_string (signature));
743 json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
744 GNUNET_free (issuer);
745 GNUNET_free (subject);
746 GNUNET_free (signature);
752 handle_vattr_collection (void* cls,
753 unsigned int d_count,
754 struct GNUNET_CREDENTIAL_Delegation *dc,
755 unsigned int c_count,
756 struct GNUNET_CREDENTIAL_Credential *cred)
758 struct IssueHandle *handle = cls;
759 struct VerifiedAttributeEntry *vattr;
763 handle->credential_request = NULL;
767 GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
770 cred_array = json_array();
771 for (i=0;i<c_count;i++)
773 cred_json = credential_to_json (cred);
774 if (NULL == cred_json)
776 json_array_append (cred_array, cred_json);
777 token_add_attr_json (handle->token,
778 handle->v_attr_head->name,
781 json_decref (cred_array);
782 vattr = handle->v_attr_head;
784 GNUNET_CONTAINER_DLL_remove (handle->v_attr_head,
787 GNUNET_free (vattr->name);
790 if (NULL == handle->v_attr_head)
792 GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
795 handle->credential_request = GNUNET_CREDENTIAL_collect (credential_handle,
797 handle->v_attr_head->name,
799 &handle_vattr_collection,
806 attr_collect_error (void *cls)
808 struct IssueHandle *handle = cls;
810 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute Error!\n");
811 handle->ns_it = NULL;
812 GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
817 attr_collect_finished (void *cls)
819 struct IssueHandle *handle = cls;
821 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n");
822 handle->ns_it = NULL;
824 if (NULL == handle->v_attr_head)
826 GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
829 handle->credential_request = GNUNET_CREDENTIAL_collect (credential_handle,
831 handle->v_attr_head->name,
833 &handle_vattr_collection,
837 * Collect attributes for token
840 attr_collect (void *cls,
841 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
843 unsigned int rd_count,
844 const struct GNUNET_GNSRECORD_Data *rd)
846 struct IssueHandle *handle = cls;
849 struct GNUNET_HashCode key;
851 GNUNET_CRYPTO_hash (label,
856 ( (NULL != handle->attr_map) &&
857 (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map,
862 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
866 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", label);
870 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
872 data = GNUNET_GNSRECORD_value_to_string (rd->record_type,
875 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
876 token_add_attr (handle->token,
881 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
886 for (; i < rd_count; i++)
888 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
890 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
893 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
894 token_add_attr (handle->token, label, data);
899 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
903 process_parallel_lookup (void *cls, uint32_t rd_count,
904 const struct GNUNET_GNSRECORD_Data *rd)
906 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
907 "Parallel lookup finished (count=%u)\n", rd_count);
908 struct ParallelLookup *parallel_lookup = cls;
909 struct ExchangeHandle *handle = parallel_lookup->handle;
913 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
914 handle->parallel_lookups_tail,
916 GNUNET_free (parallel_lookup);
919 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
921 GNUNET_CRYPTO_cpabe_decrypt (rd->data,
925 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Adding value: %s\n", data);
926 token_add_attr (handle->token,
927 parallel_lookup->label,
933 for (; i < rd_count; i++)
935 if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
937 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
940 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Adding value: %s\n", data);
941 token_add_attr (handle->token, parallel_lookup->label, data);
946 if (NULL != handle->parallel_lookups_head)
947 return; //Wait for more
949 GNUNET_SCHEDULER_cancel (handle->kill_task);
950 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
954 abort_parallel_lookups (void *cls)
956 struct ExchangeHandle *handle = cls;
957 struct ParallelLookup *lu;
958 struct ParallelLookup *tmp;
960 for (lu = handle->parallel_lookups_head;
962 GNUNET_GNS_lookup_cancel (lu->lookup_request);
963 GNUNET_free (lu->label);
965 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
966 handle->parallel_lookups_tail,
971 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
976 process_lookup_result (void *cls, uint32_t rd_count,
977 const struct GNUNET_GNSRECORD_Data *rd)
979 struct ExchangeHandle *handle = cls;
980 struct GNUNET_HashCode new_key_hash;
981 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
982 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
983 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
984 struct ParallelLookup *parallel_lookup;
990 handle->lookup_request = NULL;
993 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
994 "Number of keys %d != 1.",
996 cleanup_exchange_handle (handle);
997 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1002 ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1004 buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1006 //Calculate symmetric key from ecdh parameters
1007 GNUNET_assert (GNUNET_OK ==
1008 GNUNET_CRYPTO_ecdsa_ecdh (&handle->aud_privkey,
1011 create_sym_key_from_ecdh (&new_key_hash,
1014 size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1015 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1020 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1021 "Decrypted bytes: %zd Expected bytes: %zd\n",
1022 size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1024 scopes = GNUNET_strdup (buf);
1025 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1026 "Scopes %s\n", scopes);
1027 handle->key = GNUNET_CRYPTO_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1028 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1029 - strlen (scopes) - 1);
1031 for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1033 GNUNET_asprintf (&lookup_query,
1036 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1037 "Looking up %s\n", lookup_query);
1038 parallel_lookup = GNUNET_new (struct ParallelLookup);
1039 parallel_lookup->handle = handle;
1040 parallel_lookup->label = GNUNET_strdup (scope);
1041 parallel_lookup->lookup_request
1042 = GNUNET_GNS_lookup (gns_handle,
1044 &handle->ticket->payload->identity_key,
1045 GNUNET_GNSRECORD_TYPE_ID_ATTR,
1046 GNUNET_GNS_LO_LOCAL_MASTER,
1047 &process_parallel_lookup,
1049 GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1050 handle->parallel_lookups_tail,
1053 handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1054 &abort_parallel_lookups,
1059 * Checks a exchange message
1061 * @param cls client sending the message
1062 * @param xm message of type `struct ExchangeMessage`
1063 * @return #GNUNET_OK if @a xm is well-formed
1066 check_exchange_message (void *cls,
1067 const struct ExchangeMessage *xm)
1071 size = ntohs (xm->header.size);
1072 if (size <= sizeof (struct ExchangeMessage))
1075 return GNUNET_SYSERR;
1082 * Handler for exchange message
1085 * @param client who sent the message
1086 * @param message the message
1089 handle_exchange_message (void *cls,
1090 const struct ExchangeMessage *xm)
1092 struct ExchangeHandle *xchange_handle;
1093 struct GNUNET_SERVICE_Client *client = cls;
1097 ticket = (const char *) &xm[1];
1098 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1099 "Received EXCHANGE of `%s' from client\n",
1101 xchange_handle = GNUNET_malloc (sizeof (struct ExchangeHandle));
1102 xchange_handle->aud_privkey = xm->aud_privkey;
1103 xchange_handle->r_id = xm->id;
1104 if (GNUNET_SYSERR == ticket_parse (ticket,
1105 &xchange_handle->aud_privkey,
1106 &xchange_handle->ticket))
1108 GNUNET_free (xchange_handle);
1109 GNUNET_SERVICE_client_drop (client);
1112 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for ABE key under %s\n",
1113 xchange_handle->ticket->payload->label);
1114 GNUNET_asprintf (&lookup_query,
1116 xchange_handle->ticket->payload->label);
1117 GNUNET_SERVICE_client_continue (client);
1118 xchange_handle->client = client;
1119 xchange_handle->token = token_create (&xchange_handle->ticket->payload->identity_key,
1120 &xchange_handle->ticket->payload->identity_key);
1121 xchange_handle->lookup_request
1122 = GNUNET_GNS_lookup (gns_handle,
1124 &xchange_handle->ticket->payload->identity_key,
1125 GNUNET_GNSRECORD_TYPE_ABE_KEY,
1126 GNUNET_GNS_LO_LOCAL_MASTER,
1127 &process_lookup_result,
1129 GNUNET_free (lookup_query);
1134 * Checks an issue message
1136 * @param cls client sending the message
1137 * @param im message of type `struct IssueMessage`
1138 * @return #GNUNET_OK if @a im is well-formed
1141 check_issue_message(void *cls,
1142 const struct IssueMessage *im)
1146 size = ntohs (im->header.size);
1147 if (size <= sizeof (struct IssueMessage))
1150 return GNUNET_SYSERR;
1152 scopes = (char *) &im[1];
1153 if ('\0' != scopes[size - sizeof (struct IssueMessage) - 1])
1155 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1156 "Malformed scopes received!\n");
1158 return GNUNET_SYSERR;
1164 attr_collect_task (void *cls)
1166 struct IssueHandle *issue_handle = cls;
1168 issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1169 &issue_handle->iss_key,
1170 &attr_collect_error,
1174 &attr_collect_finished,
1179 store_bootstrap_cont (void *cls,
1183 if (GNUNET_SYSERR == success)
1185 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1186 "Failed to bootstrap ABE master %s\n",
1188 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1191 GNUNET_SCHEDULER_add_now (&attr_collect_task, cls);
1195 store_bootstrap_task (void *cls)
1197 struct IssueHandle *issue_handle = cls;
1198 struct GNUNET_GNSRECORD_Data rd[1];
1200 rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (issue_handle->abe_key,
1201 (void**)&rd[0].data);
1202 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
1203 rd[0].flags = GNUNET_GNSRECORD_RF_NONE | GNUNET_GNSRECORD_RF_PRIVATE;
1204 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1205 issue_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1206 &issue_handle->iss_key,
1210 &store_bootstrap_cont,
1215 abe_key_lookup_error (void *cls)
1217 GNUNET_SCHEDULER_add_now (&do_shutdown, cls);
1221 abe_key_lookup_result (void *cls,
1222 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1224 unsigned int rd_count,
1225 const struct GNUNET_GNSRECORD_Data *rd)
1227 struct IssueHandle *handle = cls;
1230 for (i=0;i<rd_count;i++) {
1231 if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
1233 handle->abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key ((void**)rd[i].data,
1235 GNUNET_SCHEDULER_add_now (&attr_collect_task, handle);
1239 //No ABE master found, bootstrapping...
1240 handle->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
1241 GNUNET_SCHEDULER_add_now (&store_bootstrap_task, handle);
1246 * Handler for issue message
1249 * @param client who sent the message
1250 * @param message the message
1253 handle_issue_message (void *cls,
1254 const struct IssueMessage *im)
1259 const char *v_attrs;
1261 struct GNUNET_HashCode key;
1262 struct IssueHandle *issue_handle;
1263 struct VerifiedAttributeEntry *vattr_entry;
1264 struct GNUNET_SERVICE_Client *client = cls;
1266 scopes = (const char *) &im[1];
1267 v_attrs = (const char *) &im[1] + ntohl(im->scope_len);
1268 issue_handle = GNUNET_malloc (sizeof (struct IssueHandle));
1269 issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
1271 scopes_tmp = GNUNET_strdup (scopes);
1273 for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ","))
1275 GNUNET_CRYPTO_hash (scope,
1278 GNUNET_CONTAINER_multihashmap_put (issue_handle->attr_map,
1281 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
1283 GNUNET_free (scopes_tmp);
1284 /*scopes_tmp = GNUNET_strdup (v_attrs);
1286 for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ","))
1288 vattr_entry = GNUNET_new (struct VerifiedAttributeEntry);
1289 vattr_entry->name = GNUNET_strdup (scope);
1290 GNUNET_CONTAINER_DLL_insert (issue_handle->v_attr_head,
1291 issue_handle->v_attr_tail,
1294 GNUNET_free (scopes_tmp);*/
1298 issue_handle->r_id = im->id;
1299 issue_handle->aud_key = im->aud_key;
1300 issue_handle->iss_key = im->iss_key;
1301 GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key,
1302 &issue_handle->iss_pkey);
1303 issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration);
1304 issue_handle->nonce = ntohl (im->nonce);
1305 GNUNET_SERVICE_client_continue (client);
1306 issue_handle->client = client;
1307 issue_handle->scopes = GNUNET_strdup (scopes);
1308 issue_handle->token = token_create (&issue_handle->iss_pkey,
1309 &issue_handle->aud_key);
1311 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1313 GNUNET_STRINGS_base64_encode ((char*)&rnd_key,
1315 &issue_handle->label);
1316 issue_handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
1317 &issue_handle->iss_key,
1319 &abe_key_lookup_error,
1321 &abe_key_lookup_result,
1327 * Main function that will be run
1329 * @param cls closure
1330 * @param args remaining command-line arguments
1331 * @param cfgfile name of the configuration file used (for saving, can be NULL)
1332 * @param c configuration
1336 const struct GNUNET_CONFIGURATION_Handle *c,
1337 struct GNUNET_SERVICE_Handle *server)
1341 stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
1343 //Connect to identity and namestore services
1344 ns_handle = GNUNET_NAMESTORE_connect (cfg);
1345 if (NULL == ns_handle)
1347 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
1350 gns_handle = GNUNET_GNS_connect (cfg);
1351 if (NULL == gns_handle)
1353 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1355 credential_handle = GNUNET_CREDENTIAL_connect (cfg);
1356 if (NULL == credential_handle)
1358 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
1360 identity_handle = GNUNET_IDENTITY_connect (cfg,
1365 GNUNET_CONFIGURATION_get_value_time (cfg,
1366 "identity-provider",
1367 "TOKEN_EXPIRATION_INTERVAL",
1368 &token_expiration_interval))
1370 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1371 "Time window for zone iteration: %s\n",
1372 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
1375 token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
1378 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1382 * Called whenever a client is disconnected.
1384 * @param cls closure
1385 * @param client identification of the client
1386 * @param app_ctx @a client
1389 client_disconnect_cb (void *cls,
1390 struct GNUNET_SERVICE_Client *client,
1393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1394 "Client %p disconnected\n",
1400 * Add a client to our list of active clients.
1403 * @param client client to add
1404 * @param mq message queue for @a client
1405 * @return internal namestore client structure for this client
1408 client_connect_cb (void *cls,
1409 struct GNUNET_SERVICE_Client *client,
1410 struct GNUNET_MQ_Handle *mq)
1412 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1413 "Client %p connected\n",
1421 * Define "main" method using service macro.
1424 ("identity-provider",
1425 GNUNET_SERVICE_OPTION_NONE,
1428 &client_disconnect_cb,
1430 GNUNET_MQ_hd_var_size (issue_message,
1431 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE,
1432 struct IssueMessage,
1434 GNUNET_MQ_hd_var_size (exchange_message,
1435 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE,
1436 struct ExchangeMessage,
1438 GNUNET_MQ_handler_end());
1439 /* end of gnunet-service-identity-provider.c */