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_abe_lib.h"
34 #include "gnunet_credential_service.h"
35 #include "gnunet_statistics_service.h"
36 #include "gnunet_gns_service.h"
37 #include "gnunet_identity_provider_plugin.h"
38 #include "gnunet_identity_attribute_lib.h"
39 #include "gnunet_signatures.h"
40 #include "identity_provider.h"
48 * Normal operation state
50 #define STATE_POST_INIT 1
53 * Minimum interval between updates
55 #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
58 * Standard token expiration time
60 #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
65 static struct GNUNET_IDENTITY_Handle *identity_handle;
70 static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database;
75 static char *db_lib_name;
78 * Token expiration interval
80 static struct GNUNET_TIME_Relative token_expiration_interval;
85 static struct GNUNET_NAMESTORE_Handle *ns_handle;
90 static struct GNUNET_GNS_Handle *gns_handle;
95 static struct GNUNET_CREDENTIAL_Handle *credential_handle;
100 static struct GNUNET_STATISTICS_Handle *stats_handle;
105 static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
110 static struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
115 static struct GNUNET_SCHEDULER_Task *timeout_task;
120 static struct GNUNET_SCHEDULER_Task *update_task;
124 * Currently processed token
126 static struct IdentityToken *token;
129 * Label for currently processed token
134 * Scopes for processed token
139 * Handle to the statistics service.
141 static struct GNUNET_STATISTICS_Handle *stats;
146 static const struct GNUNET_CONFIGURATION_Handle *cfg;
154 * A ticket iteration operation.
156 struct TicketIteration
161 struct TicketIteration *next;
166 struct TicketIteration *prev;
169 * Client which intiated this zone iteration
171 struct IdpClient *client;
174 * Key of the identity we are iterating over.
176 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
179 * Identity is audience
181 uint32_t is_audience;
184 * The operation id fot the iteration in the response for the client
189 * Offset of the iteration used to address next result of the
190 * iteration in the store
192 * Initialy set to 0 in handle_iteration_start
193 * Incremented with by every call to handle_iteration_next
202 * Callback after an ABE bootstrap
205 * @param abe_key the ABE key that exists or was created
208 (*AbeBootstrapResult) (void *cls,
209 struct GNUNET_ABE_AbeMasterKey *abe_key);
212 struct AbeBootstrapHandle
215 * Function to call when finished
217 AbeBootstrapResult proc;
225 * Key of the zone we are iterating over.
227 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
230 * Namestore Queue Entry
232 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
235 * The issuer egos ABE master key
237 struct GNUNET_ABE_AbeMasterKey *abe_key;
241 * An attribute iteration operation.
243 struct AttributeIterator
246 * Next element in the DLL
248 struct AttributeIterator *next;
251 * Previous element in the DLL
253 struct AttributeIterator *prev;
256 * IDP client which intiated this zone iteration
258 struct IdpClient *client;
261 * Key of the zone we are iterating over.
263 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
266 * The issuer egos ABE master key
268 struct GNUNET_ABE_AbeMasterKey *abe_key;
273 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
276 * The operation id fot the zone iteration in the response for the client
293 struct GNUNET_SERVICE_Client *client;
296 * Message queue for transmission to @e client
298 struct GNUNET_MQ_Handle *mq;
302 * Attribute iteration operations in
303 * progress initiated by this client
305 struct AttributeIterator *op_head;
309 * Attribute iteration operations
310 * in progress initiated by this client
312 struct AttributeIterator *op_tail;
315 * Head of DLL of ticket iteration ops
317 struct TicketIteration *ticket_iter_head;
320 * Tail of DLL of ticket iteration ops
322 struct TicketIteration *ticket_iter_tail;
326 * Head of DLL of ticket revocation ops
328 struct TicketRevocationHandle *revocation_list_head;
331 * Tail of DLL of ticket revocation ops
333 struct TicketRevocationHandle *revocation_list_tail;
338 struct AttributeStoreHandle
344 struct IdpClient *client;
349 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
354 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
357 * The issuer egos ABE master key
359 struct GNUNET_ABE_AbeMasterKey *abe_key;
364 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
367 * The attribute to store
369 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
379 struct ParallelLookup;
381 struct ConsumeTicketHandle
387 struct IdpClient *client;
392 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
397 struct GNUNET_GNS_LookupRequest *lookup_request;
402 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
407 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
412 struct ParallelLookup *parallel_lookups_head;
417 struct ParallelLookup *parallel_lookups_tail;
422 struct GNUNET_SCHEDULER_Task *kill_task;
427 struct GNUNET_ABE_AbeKey *key;
432 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
437 struct GNUNET_TIME_Absolute lookup_start_time;
446 * Handle for a parallel GNS lookup job
448 struct ParallelLookup
451 struct ParallelLookup *next;
454 struct ParallelLookup *prev;
456 /* The GNS request */
457 struct GNUNET_GNS_LookupRequest *lookup_request;
459 /* The handle the return to */
460 struct ConsumeTicketHandle *handle;
465 struct GNUNET_TIME_Absolute lookup_start_time;
467 /* The label to look up */
472 * Ticket revocation request handle
474 struct TicketRevocationHandle
479 struct TicketRevocationHandle *next;
484 struct TicketRevocationHandle *prev;
489 struct IdpClient *client;
492 * Attributes to reissue
494 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
497 * Attributes to revoke
499 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *rvk_attrs;
504 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
509 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
514 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
519 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
524 struct GNUNET_ABE_AbeMasterKey *abe_key;
540 * Ticket issue request handle
542 struct TicketIssueHandle
548 struct IdpClient *client;
551 * Attributes to issue
553 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
558 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
563 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
568 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
578 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
586 struct EgoEntry *next;
591 struct EgoEntry *prev;
596 struct GNUNET_IDENTITY_Ego *ego;
599 * Attribute map. Contains the attributes as json_t
601 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
615 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
618 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
620 GNUNET_free (db_lib_name);
622 if (NULL != timeout_task)
623 GNUNET_SCHEDULER_cancel (timeout_task);
624 if (NULL != update_task)
625 GNUNET_SCHEDULER_cancel (update_task);
626 if (NULL != identity_handle)
627 GNUNET_IDENTITY_disconnect (identity_handle);
628 if (NULL != gns_handle)
629 GNUNET_GNS_disconnect (gns_handle);
630 if (NULL != credential_handle)
631 GNUNET_CREDENTIAL_disconnect (credential_handle);
633 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
635 GNUNET_NAMESTORE_cancel (ns_qe);
636 if (NULL != ns_handle)
637 GNUNET_NAMESTORE_disconnect (ns_handle);
638 if (NULL != stats_handle)
639 GNUNET_STATISTICS_destroy (stats_handle, GNUNET_NO);
651 * @param tc task context
654 do_shutdown (void *cls)
656 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
657 "Shutting down...\n");
662 * Finished storing newly bootstrapped ABE key
665 bootstrap_store_cont (void *cls,
669 struct AbeBootstrapHandle *abh = cls;
670 if (GNUNET_SYSERR == success)
672 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
673 "Failed to bootstrap ABE master %s\n",
675 abh->proc (abh->proc_cls, NULL);
676 GNUNET_free (abh->abe_key);
680 abh->proc (abh->proc_cls, abh->abe_key);
685 * Generates and stores a new ABE key
688 bootstrap_store_task (void *cls)
690 struct AbeBootstrapHandle *abh = cls;
691 struct GNUNET_GNSRECORD_Data rd[1];
694 rd[0].data_size = GNUNET_ABE_cpabe_serialize_master_key (abh->abe_key,
697 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
698 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
699 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
700 abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
705 &bootstrap_store_cont,
711 * Error checking for ABE master
714 bootstrap_abe_error (void *cls)
716 struct AbeBootstrapHandle *abh = cls;
718 abh->proc (abh->proc_cls, NULL);
724 * Handle ABE lookup in namestore
727 bootstrap_abe_result (void *cls,
728 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
730 unsigned int rd_count,
731 const struct GNUNET_GNSRECORD_Data *rd)
733 struct AbeBootstrapHandle *abh = cls;
734 struct GNUNET_ABE_AbeMasterKey *abe_key;
737 for (i=0;i<rd_count;i++) {
738 if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
740 abe_key = GNUNET_ABE_cpabe_deserialize_master_key (rd[i].data,
742 abh->proc (abh->proc_cls, abe_key);
747 //No ABE master found, bootstrapping...
748 abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
749 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
753 * Bootstrap ABE master if it does not yet exists.
754 * Will call the AbeBootstrapResult processor when done.
755 * will always recreate the ABE key of GNUNET_YES == recreate
758 bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
759 AbeBootstrapResult proc,
763 struct AbeBootstrapHandle *abh;
765 abh = GNUNET_new (struct AbeBootstrapHandle);
768 abh->identity = *identity;
769 if (GNUNET_YES == recreate)
771 abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
772 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
774 abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
777 &bootstrap_abe_error,
779 &bootstrap_abe_result,
787 create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
788 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
789 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
791 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
793 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
795 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
796 static const char ctx_key[] = "gnuid-aes-ctx-key";
797 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
798 new_key_hash, sizeof (struct GNUNET_HashCode),
799 ctx_key, strlen (ctx_key),
801 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
802 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
803 new_key_hash, sizeof (struct GNUNET_HashCode),
804 ctx_iv, strlen (ctx_iv),
810 cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
812 if (NULL != handle->attrs)
813 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
814 if (NULL != handle->ns_qe)
815 GNUNET_NAMESTORE_cancel (handle->ns_qe);
816 GNUNET_free (handle);
821 send_ticket_result (struct IdpClient *client,
823 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
824 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
826 struct TicketResultMessage *irm;
827 struct GNUNET_MQ_Envelope *env;
828 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
830 /* store ticket in DB */
831 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
835 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
836 "Unable to store ticket after issue\n");
840 env = GNUNET_MQ_msg_extra (irm,
841 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
842 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
843 ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
844 *ticket_buf = *ticket;
845 irm->id = htonl (r_id);
846 GNUNET_MQ_send (client->mq,
851 store_ticket_issue_cont (void *cls,
855 struct TicketIssueHandle *handle = cls;
857 handle->ns_qe = NULL;
858 if (GNUNET_SYSERR == success)
860 cleanup_ticket_issue_handle (handle);
861 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
863 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
866 send_ticket_result (handle->client,
870 cleanup_ticket_issue_handle (handle);
876 serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
877 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
878 const struct GNUNET_ABE_AbeKey *rp_key,
879 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
882 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
883 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
885 char *serialized_key;
891 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
892 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
893 struct GNUNET_HashCode new_key_hash;
896 size = GNUNET_ABE_cpabe_serialize_key (rp_key,
897 (void**)&serialized_key);
899 for (le = attrs->list_head; NULL != le; le = le->next) {
900 attrs_str_len += strlen (le->claim->name) + 1;
902 buf = GNUNET_malloc (attrs_str_len + size);
904 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
905 "Writing attributes\n");
906 for (le = attrs->list_head; NULL != le; le = le->next) {
907 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
908 "%s\n", le->claim->name);
911 GNUNET_memcpy (write_ptr,
913 strlen (le->claim->name));
914 write_ptr[strlen (le->claim->name)] = ',';
915 write_ptr += strlen (le->claim->name) + 1;
918 write_ptr[0] = '\0'; //replace last , with a 0-terminator
920 GNUNET_memcpy (write_ptr,
923 GNUNET_free (serialized_key);
924 // ECDH keypair E = eG
925 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
926 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
928 enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
929 // Derived key K = H(eB)
930 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
933 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
934 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
935 size + attrs_str_len,
938 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
940 GNUNET_memcpy (*result,
942 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
943 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
946 GNUNET_free (enc_keyinfo);
948 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
954 issue_ticket_after_abe_bootstrap (void *cls,
955 struct GNUNET_ABE_AbeMasterKey *abe_key)
957 struct TicketIssueHandle *ih = cls;
958 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
959 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
960 struct GNUNET_GNSRECORD_Data code_record[1];
961 struct GNUNET_ABE_AbeKey *rp_key;
962 char *code_record_data;
968 size_t code_record_len;
970 //Create new ABE key for RP
972 for (le = ih->attrs->list_head; NULL != le; le = le->next)
974 attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
976 for (le = ih->attrs->list_head; NULL != le; le = le->next) {
977 GNUNET_asprintf (&policy, "%s_%lu",
980 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
981 "Adding attribute to key: %s\n",
987 rp_key = GNUNET_ABE_cpabe_create_key (abe_key,
990 //TODO review this wireformat
991 code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
996 code_record[0].data = code_record_data;
997 code_record[0].data_size = code_record_len;
998 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
999 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1000 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1002 label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
1005 ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1010 &store_ticket_issue_cont,
1012 //for (; i > 0; i--)
1013 // GNUNET_free (attrs[i-1]);
1014 GNUNET_free (ecdhe_privkey);
1015 GNUNET_free (label);
1016 GNUNET_free (attrs);
1017 GNUNET_free (code_record_data);
1018 GNUNET_ABE_cpabe_delete_key (rp_key,
1020 GNUNET_ABE_cpabe_delete_master_key (abe_key);
1025 * Checks a ticket issue message
1027 * @param cls client sending the message
1028 * @param im message of type `struct TicketIssueMessage`
1029 * @return #GNUNET_OK if @a im is well-formed
1032 check_issue_ticket_message(void *cls,
1033 const struct IssueTicketMessage *im)
1037 size = ntohs (im->header.size);
1038 if (size <= sizeof (struct IssueTicketMessage))
1041 return GNUNET_SYSERR;
1049 * Handler for ticket issue message
1052 * @param client who sent the message
1053 * @param message the message
1056 handle_issue_ticket_message (void *cls,
1057 const struct IssueTicketMessage *im)
1059 struct TicketIssueHandle *ih;
1060 struct IdpClient *idp = cls;
1063 ih = GNUNET_new (struct TicketIssueHandle);
1064 attrs_len = ntohs (im->attr_len);
1065 ih->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&im[1], attrs_len);
1066 ih->r_id = ntohl (im->id);
1068 ih->identity = im->identity;
1069 GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
1070 &ih->ticket.identity);
1071 ih->ticket.audience = im->rp;
1073 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1075 bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
1076 GNUNET_SERVICE_client_continue (idp->client);
1080 /**********************************************************
1082 **********************************************************/
1085 * Cleanup revoke handle
1088 cleanup_revoke_ticket_handle (struct TicketRevocationHandle *handle)
1090 if (NULL != handle->attrs)
1091 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
1092 if (NULL != handle->rvk_attrs)
1093 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->rvk_attrs);
1094 if (NULL != handle->abe_key)
1095 GNUNET_ABE_cpabe_delete_master_key (handle->abe_key);
1096 if (NULL != handle->ns_qe)
1097 GNUNET_NAMESTORE_cancel (handle->ns_qe);
1098 if (NULL != handle->ns_it)
1099 GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
1100 GNUNET_free (handle);
1105 * Send revocation result
1108 send_revocation_finished (struct TicketRevocationHandle *rh,
1111 struct GNUNET_MQ_Envelope *env;
1112 struct RevokeTicketResultMessage *trm;
1114 env = GNUNET_MQ_msg (trm,
1115 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT);
1116 trm->id = htonl (rh->r_id);
1117 trm->success = htonl (success);
1118 GNUNET_MQ_send (rh->client->mq,
1120 GNUNET_CONTAINER_DLL_remove (rh->client->revocation_list_head,
1121 rh->client->revocation_list_tail,
1127 * Process ticket from database
1129 * @param cls struct TicketIterationProcResult
1130 * @param ticket the ticket
1131 * @param attrs the attributes
1134 ticket_reissue_proc (void *cls,
1135 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1136 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
1139 revocation_reissue_tickets (struct TicketRevocationHandle *rh);
1142 static void reissue_next (void *cls)
1144 struct TicketRevocationHandle *rh = cls;
1145 revocation_reissue_tickets (rh);
1150 reissue_ticket_cont (void *cls,
1154 struct TicketRevocationHandle *rh = cls;
1157 if (GNUNET_SYSERR == success)
1159 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1161 send_revocation_finished (rh, GNUNET_SYSERR);
1162 cleanup_revoke_ticket_handle (rh);
1166 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
1171 * Process ticket from database
1173 * @param cls struct TicketIterationProcResult
1174 * @param ticket the ticket
1175 * @param attrs the attributes
1178 ticket_reissue_proc (void *cls,
1179 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1180 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
1182 struct TicketRevocationHandle *rh = cls;
1183 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
1184 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le_rollover;
1185 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
1186 struct GNUNET_GNSRECORD_Data code_record[1];
1187 struct GNUNET_ABE_AbeKey *rp_key;
1188 char *code_record_data;
1195 size_t code_record_len;
1200 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1201 "Iteration done\n");
1205 if (0 == memcmp (&ticket->audience,
1206 &rh->ticket.audience,
1207 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
1209 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1210 "Do not reissue for this identity.!\n");
1213 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
1218 * Check if any attribute of this ticket intersects with a rollover attribute
1220 reissue_ticket = GNUNET_NO;
1221 for (le = attrs->list_head; NULL != le; le = le->next)
1223 for (le_rollover = rh->rvk_attrs->list_head;
1224 NULL != le_rollover;
1225 le_rollover = le_rollover->next)
1227 if (0 == strcmp (le_rollover->claim->name,
1230 reissue_ticket = GNUNET_YES;
1231 le->claim->version = le_rollover->claim->version;
1236 if (GNUNET_NO == reissue_ticket)
1238 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1239 "Skipping ticket.\n");
1242 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
1248 //Create new ABE key for RP
1251 /* If this is the RP we want to revoke attributes of, the do so */
1253 for (le = attrs->list_head; NULL != le; le = le->next)
1255 attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1257 for (le = attrs->list_head; NULL != le; le = le->next) {
1258 GNUNET_asprintf (&policy, "%s_%lu",
1260 le->claim->version);
1261 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1262 "Recreating key with %s\n", policy);
1263 attr_arr[i] = policy;
1267 rp_key = GNUNET_ABE_cpabe_create_key (rh->abe_key,
1270 //TODO review this wireformat
1271 code_record_len = serialize_abe_keyinfo2 (ticket,
1276 code_record[0].data = code_record_data;
1277 code_record[0].data_size = code_record_len;
1278 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1279 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1280 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1282 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
1285 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1290 &reissue_ticket_cont,
1292 //for (; i > 0; i--)
1293 // GNUNET_free (attr_arr[i-1]);
1294 GNUNET_free (ecdhe_privkey);
1295 GNUNET_free (label);
1296 GNUNET_free (attr_arr);
1297 GNUNET_free (code_record_data);
1298 GNUNET_ABE_cpabe_delete_key (rp_key, GNUNET_YES);
1302 /* Prototype for below function */
1304 attr_reenc_cont (void *cls,
1309 revocation_reissue_tickets (struct TicketRevocationHandle *rh)
1312 /* Done, issue new keys */
1313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1314 "Revocation Phase III: Reissuing Tickets\n");
1315 if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
1316 &rh->ticket.identity,
1319 &ticket_reissue_proc,
1324 if (GNUNET_NO == ret)
1326 send_revocation_finished (rh, GNUNET_OK);
1327 cleanup_revoke_ticket_handle (rh);
1333 * Revoke next attribte by reencryption with
1337 reenc_next_attribute (struct TicketRevocationHandle *rh)
1339 struct GNUNET_GNSRECORD_Data rd[1];
1348 if (NULL == rh->attrs->list_head)
1350 revocation_reissue_tickets (rh);
1353 buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim);
1354 buf = GNUNET_malloc (buf_size);
1355 GNUNET_IDENTITY_ATTRIBUTE_serialize (rh->attrs->list_head->claim,
1357 rh->attrs->list_head->claim->version++;
1358 GNUNET_asprintf (&policy, "%s_%lu",
1359 rh->attrs->list_head->claim->name,
1360 rh->attrs->list_head->claim->version);
1361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1362 "Encrypting with policy %s\n", policy);
1364 * Encrypt the attribute value and store in namestore
1366 enc_size = GNUNET_ABE_cpabe_encrypt (buf,
1372 GNUNET_free (policy);
1373 rd[0].data_size = enc_size + sizeof (uint32_t);
1374 rd_buf = GNUNET_malloc (rd[0].data_size);
1375 attr_ver = htonl (rh->attrs->list_head->claim->version);
1376 GNUNET_memcpy (rd_buf,
1379 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1382 rd[0].data = rd_buf;
1383 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1384 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1385 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1386 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1388 rh->attrs->list_head->claim->name,
1393 GNUNET_free (enc_buf);
1394 GNUNET_free (rd_buf);
1398 * Namestore callback after revoked attribute
1402 attr_reenc_cont (void *cls,
1406 struct TicketRevocationHandle *rh = cls;
1407 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
1409 if (GNUNET_SYSERR == success)
1411 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1412 "Failed to reencrypt attribute %s\n",
1414 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1417 if (NULL == rh->attrs->list_head)
1419 revocation_reissue_tickets (rh);
1422 le = rh->attrs->list_head;
1423 GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1424 rh->attrs->list_tail,
1426 GNUNET_assert (NULL != rh->rvk_attrs);
1427 GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
1428 rh->rvk_attrs->list_tail,
1432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1433 "Re-encrypting next attribute\n");
1434 reenc_next_attribute (rh);
1439 process_attributes_to_update (void *cls,
1440 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1441 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
1443 struct TicketRevocationHandle *rh = cls;
1445 rh->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_dup (attrs);
1446 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1447 "Revocation Phase I: Collecting attributes\n");
1448 /* Reencrypt all attributes with new key */
1449 if (NULL == rh->attrs->list_head)
1451 /* No attributes to reencrypt */
1452 send_revocation_finished (rh, GNUNET_OK);
1453 cleanup_revoke_ticket_handle (rh);
1456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1457 "Revocation Phase II: Re-encrypting attributes\n");
1458 reenc_next_attribute (rh);
1466 get_ticket_after_abe_bootstrap (void *cls,
1467 struct GNUNET_ABE_AbeMasterKey *abe_key)
1469 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1470 "Finished ABE bootstrap\n");
1471 struct TicketRevocationHandle *rh = cls;
1472 rh->abe_key = abe_key;
1473 TKT_database->get_ticket_attributes (TKT_database->cls,
1475 &process_attributes_to_update,
1480 * Checks a ticket revocation message
1482 * @param cls client sending the message
1483 * @param im message of type `struct RevokeTicketMessage`
1484 * @return #GNUNET_OK if @a im is well-formed
1487 check_revoke_ticket_message(void *cls,
1488 const struct RevokeTicketMessage *im)
1492 size = ntohs (im->header.size);
1493 if (size <= sizeof (struct RevokeTicketMessage))
1496 return GNUNET_SYSERR;
1502 * Handler for ticket revocation message
1505 * @param client who sent the message
1506 * @param message the message
1509 handle_revoke_ticket_message (void *cls,
1510 const struct RevokeTicketMessage *rm)
1512 struct TicketRevocationHandle *rh;
1513 struct IdpClient *idp = cls;
1514 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
1516 rh = GNUNET_new (struct TicketRevocationHandle);
1517 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1];
1518 rh->rvk_attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
1519 rh->ticket = *ticket;
1520 rh->r_id = ntohl (rm->id);
1522 rh->identity = rm->identity;
1523 GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
1524 &rh->ticket.identity);
1525 GNUNET_CONTAINER_DLL_insert (idp->revocation_list_head,
1526 idp->revocation_list_tail,
1528 bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO);
1529 GNUNET_SERVICE_client_continue (idp->client);
1535 cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
1537 if (NULL != handle->key)
1538 GNUNET_ABE_cpabe_delete_key (handle->key,
1540 if (NULL != handle->attrs)
1541 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
1542 GNUNET_free (handle);
1548 * Checks a ticket consume message
1550 * @param cls client sending the message
1551 * @param im message of type `struct ConsumeTicketMessage`
1552 * @return #GNUNET_OK if @a im is well-formed
1555 check_consume_ticket_message(void *cls,
1556 const struct ConsumeTicketMessage *cm)
1560 size = ntohs (cm->header.size);
1561 if (size <= sizeof (struct ConsumeTicketMessage))
1564 return GNUNET_SYSERR;
1570 process_parallel_lookup2 (void *cls, uint32_t rd_count,
1571 const struct GNUNET_GNSRECORD_Data *rd)
1573 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1574 "Parallel lookup finished (count=%u)\n", rd_count);
1575 struct ParallelLookup *parallel_lookup = cls;
1576 struct ConsumeTicketHandle *handle = parallel_lookup->handle;
1577 struct ConsumeTicketResultMessage *crm;
1578 struct GNUNET_MQ_Envelope *env;
1579 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *attr_le;
1580 struct GNUNET_TIME_Absolute decrypt_duration;
1586 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1587 handle->parallel_lookups_tail,
1589 GNUNET_free (parallel_lookup->label);
1591 GNUNET_STATISTICS_update (stats_handle,
1592 "attribute_lookup_time_total",
1593 GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us,
1595 GNUNET_STATISTICS_update (stats_handle,
1596 "attribute_lookups_count",
1601 GNUNET_free (parallel_lookup);
1603 GNUNET_break(0);//TODO
1604 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1606 decrypt_duration = GNUNET_TIME_absolute_get ();
1607 attr_len = GNUNET_ABE_cpabe_decrypt (rd->data + sizeof (uint32_t),
1608 rd->data_size - sizeof (uint32_t),
1611 if (GNUNET_SYSERR != attr_len)
1613 GNUNET_STATISTICS_update (stats_handle,
1614 "abe_decrypt_time_total",
1615 GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us,
1617 GNUNET_STATISTICS_update (stats_handle,
1618 "abe_decrypt_count",
1622 attr_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
1623 attr_le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (data,
1625 attr_le->claim->version = ntohl(*(uint32_t*)rd->data);
1626 GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
1627 handle->attrs->list_tail,
1632 if (NULL != handle->parallel_lookups_head)
1633 return; //Wait for more
1634 /* Else we are done */
1636 /* Store ticket in DB */
1637 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1641 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1642 "Unable to store ticket after consume\n");
1646 GNUNET_SCHEDULER_cancel (handle->kill_task);
1647 attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (handle->attrs);
1648 env = GNUNET_MQ_msg_extra (crm,
1650 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
1651 crm->id = htonl (handle->r_id);
1652 crm->attrs_len = htons (attrs_len);
1653 crm->identity = handle->ticket.identity;
1654 data_tmp = (char *) &crm[1];
1655 GNUNET_IDENTITY_ATTRIBUTE_list_serialize (handle->attrs,
1657 GNUNET_MQ_send (handle->client->mq, env);
1658 cleanup_consume_ticket_handle (handle);
1662 abort_parallel_lookups2 (void *cls)
1664 struct ConsumeTicketHandle *handle = cls;
1665 struct ParallelLookup *lu;
1666 struct ParallelLookup *tmp;
1667 struct AttributeResultMessage *arm;
1668 struct GNUNET_MQ_Envelope *env;
1670 for (lu = handle->parallel_lookups_head;
1672 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1673 GNUNET_free (lu->label);
1675 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1676 handle->parallel_lookups_tail,
1681 env = GNUNET_MQ_msg (arm,
1682 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1683 arm->id = htonl (handle->r_id);
1684 arm->attr_len = htons (0);
1685 GNUNET_MQ_send (handle->client->mq, env);
1691 process_consume_abe_key (void *cls, uint32_t rd_count,
1692 const struct GNUNET_GNSRECORD_Data *rd)
1694 struct ConsumeTicketHandle *handle = cls;
1695 struct GNUNET_HashCode new_key_hash;
1696 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1697 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1698 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1699 struct ParallelLookup *parallel_lookup;
1705 handle->lookup_request = NULL;
1708 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1709 "Number of keys %d != 1.",
1711 cleanup_consume_ticket_handle (handle);
1712 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1717 ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1719 buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1721 //Calculate symmetric key from ecdh parameters
1722 GNUNET_assert (GNUNET_OK ==
1723 GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
1726 create_sym_key_from_ecdh (&new_key_hash,
1729 size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1730 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1735 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1736 "Decrypted bytes: %zd Expected bytes: %zd\n",
1737 size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1738 GNUNET_STATISTICS_update (stats_handle,
1739 "abe_key_lookup_time_total",
1740 GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us,
1742 GNUNET_STATISTICS_update (stats_handle,
1743 "abe_key_lookups_count",
1746 scopes = GNUNET_strdup (buf);
1747 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1748 "Scopes %s\n", scopes);
1749 handle->key = GNUNET_ABE_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1750 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1751 - strlen (scopes) - 1);
1753 for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1755 GNUNET_asprintf (&lookup_query,
1758 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1759 "Looking up %s\n", lookup_query);
1760 parallel_lookup = GNUNET_new (struct ParallelLookup);
1761 parallel_lookup->handle = handle;
1762 parallel_lookup->label = GNUNET_strdup (scope);
1763 parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get();
1764 parallel_lookup->lookup_request
1765 = GNUNET_GNS_lookup (gns_handle,
1767 &handle->ticket.identity,
1768 GNUNET_GNSRECORD_TYPE_ID_ATTR,
1769 GNUNET_GNS_LO_DEFAULT,
1770 &process_parallel_lookup2,
1772 GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1773 handle->parallel_lookups_tail,
1775 GNUNET_free (lookup_query);
1777 GNUNET_free (scopes);
1779 handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1780 &abort_parallel_lookups2,
1787 * Handler for ticket issue message
1790 * @param client who sent the message
1791 * @param message the message
1794 handle_consume_ticket_message (void *cls,
1795 const struct ConsumeTicketMessage *cm)
1797 struct ConsumeTicketHandle *ch;
1798 struct IdpClient *idp = cls;
1802 ch = GNUNET_new (struct ConsumeTicketHandle);
1803 ch->r_id = ntohl (cm->id);
1805 ch->identity = cm->identity;
1806 ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
1807 GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
1809 ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
1810 rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
1812 GNUNET_asprintf (&lookup_query,
1815 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1816 "Looking for ABE key under %s\n", lookup_query);
1817 ch->lookup_start_time = GNUNET_TIME_absolute_get ();
1819 = GNUNET_GNS_lookup (gns_handle,
1821 &ch->ticket.identity,
1822 GNUNET_GNSRECORD_TYPE_ABE_KEY,
1823 GNUNET_GNS_LO_DEFAULT,
1824 &process_consume_abe_key,
1826 GNUNET_free (rnd_label);
1827 GNUNET_free (lookup_query);
1828 GNUNET_SERVICE_client_continue (idp->client);
1832 cleanup_as_handle (struct AttributeStoreHandle *handle)
1834 if (NULL != handle->claim)
1835 GNUNET_free (handle->claim);
1836 if (NULL != handle->abe_key)
1837 GNUNET_ABE_cpabe_delete_master_key (handle->abe_key);
1838 GNUNET_free (handle);
1842 attr_store_cont (void *cls,
1846 struct AttributeStoreHandle *as_handle = cls;
1847 struct GNUNET_MQ_Envelope *env;
1848 struct AttributeStoreResultMessage *acr_msg;
1850 if (GNUNET_SYSERR == success)
1852 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1853 "Failed to store attribute %s\n",
1855 cleanup_as_handle (as_handle);
1856 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1860 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1861 "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1862 env = GNUNET_MQ_msg (acr_msg,
1863 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
1864 acr_msg->id = htonl (as_handle->r_id);
1865 acr_msg->op_result = htonl (GNUNET_OK);
1866 GNUNET_MQ_send (as_handle->client->mq,
1868 cleanup_as_handle (as_handle);
1872 attr_store_task (void *cls)
1874 struct AttributeStoreHandle *as_handle = cls;
1875 struct GNUNET_GNSRECORD_Data rd[1];
1884 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1885 "Storing attribute\n");
1886 buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (as_handle->claim);
1887 buf = GNUNET_malloc (buf_size);
1889 GNUNET_IDENTITY_ATTRIBUTE_serialize (as_handle->claim,
1892 GNUNET_asprintf (&policy,
1894 as_handle->claim->name,
1895 as_handle->claim->version);
1896 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1897 "Encrypting with policy %s\n", policy);
1899 * Encrypt the attribute value and store in namestore
1901 enc_size = GNUNET_ABE_cpabe_encrypt (buf,
1907 GNUNET_free (policy);
1908 rd[0].data_size = enc_size + sizeof (uint32_t);
1909 rd_buf = GNUNET_malloc (rd[0].data_size);
1910 attr_ver = htonl (as_handle->claim->version);
1911 GNUNET_memcpy (rd_buf,
1914 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1917 rd[0].data = rd_buf;
1918 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1919 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1920 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1921 as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1922 &as_handle->identity,
1923 as_handle->claim->name,
1928 GNUNET_free (enc_buf);
1929 GNUNET_free (rd_buf);
1934 store_after_abe_bootstrap (void *cls,
1935 struct GNUNET_ABE_AbeMasterKey *abe_key)
1937 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1938 "Finished ABE bootstrap\n");
1939 struct AttributeStoreHandle *ash = cls;
1940 ash->abe_key = abe_key;
1941 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1945 * Checks a store message
1947 * @param cls client sending the message
1948 * @param sam message of type `struct AttributeStoreMessage`
1949 * @return #GNUNET_OK if @a im is well-formed
1952 check_attribute_store_message(void *cls,
1953 const struct AttributeStoreMessage *sam)
1957 size = ntohs (sam->header.size);
1958 if (size <= sizeof (struct AttributeStoreMessage))
1961 return GNUNET_SYSERR;
1969 * Handler for store message
1972 * @param client who sent the message
1973 * @param message the message
1976 handle_attribute_store_message (void *cls,
1977 const struct AttributeStoreMessage *sam)
1979 struct AttributeStoreHandle *as_handle;
1980 struct IdpClient *idp = cls;
1982 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1983 "Received ATTRIBUTE_STORE message\n");
1985 data_len = ntohs (sam->attr_len);
1987 as_handle = GNUNET_new (struct AttributeStoreHandle);
1988 as_handle->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&sam[1],
1991 as_handle->r_id = ntohl (sam->id);
1992 as_handle->identity = sam->identity;
1993 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1994 &as_handle->identity_pkey);
1996 GNUNET_SERVICE_client_continue (idp->client);
1997 as_handle->client = idp;
1998 bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
2002 cleanup_iter_handle (struct AttributeIterator *ai)
2004 if (NULL != ai->abe_key)
2005 GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
2006 GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
2007 ai->client->op_tail,
2013 attr_iter_error (void *cls)
2015 struct AttributeIterator *ai = cls;
2017 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2018 "Failed to iterate over attributes\n");
2019 cleanup_iter_handle (ai);
2020 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
2024 attr_iter_finished (void *cls)
2026 struct AttributeIterator *ai = cls;
2027 struct GNUNET_MQ_Envelope *env;
2028 struct AttributeResultMessage *arm;
2030 env = GNUNET_MQ_msg (arm,
2031 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
2032 arm->id = htonl (ai->request_id);
2033 arm->attr_len = htons (0);
2034 GNUNET_MQ_send (ai->client->mq, env);
2035 cleanup_iter_handle (ai);
2039 attr_iter_cb (void *cls,
2040 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
2042 unsigned int rd_count,
2043 const struct GNUNET_GNSRECORD_Data *rd)
2045 struct AttributeIterator *ai = cls;
2046 struct AttributeResultMessage *arm;
2047 struct GNUNET_ABE_AbeKey *key;
2048 struct GNUNET_MQ_Envelope *env;
2049 ssize_t msg_extra_len;
2058 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2062 if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
2063 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2066 attr_ver = ntohl(*((uint32_t*)rd->data));
2067 GNUNET_asprintf (&policy, "%s_%lu",
2071 key = GNUNET_ABE_cpabe_create_key (ai->abe_key,
2073 msg_extra_len = GNUNET_ABE_cpabe_decrypt (rd->data+sizeof (uint32_t),
2074 rd->data_size-sizeof (uint32_t),
2078 GNUNET_ABE_cpabe_delete_key (key,
2080 //GNUNET_free (policy);
2081 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2082 "Found attribute: %s\n", label);
2083 env = GNUNET_MQ_msg_extra (arm,
2085 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
2086 arm->id = htonl (ai->request_id);
2087 arm->attr_len = htons (msg_extra_len);
2088 GNUNET_CRYPTO_ecdsa_key_get_public (zone,
2090 data_tmp = (char *) &arm[1];
2091 GNUNET_memcpy (data_tmp,
2094 GNUNET_MQ_send (ai->client->mq, env);
2095 GNUNET_free (attr_ser);
2096 GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
2102 iterate_after_abe_bootstrap (void *cls,
2103 struct GNUNET_ABE_AbeMasterKey *abe_key)
2105 struct AttributeIterator *ai = cls;
2106 ai->abe_key = abe_key;
2107 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
2113 &attr_iter_finished,
2118 iterate_next_after_abe_bootstrap (void *cls,
2119 struct GNUNET_ABE_AbeMasterKey *abe_key)
2121 struct AttributeIterator *ai = cls;
2122 ai->abe_key = abe_key;
2123 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2129 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_START message
2131 * @param cls the client sending the message
2132 * @param zis_msg message from the client
2135 handle_iteration_start (void *cls,
2136 const struct AttributeIterationStartMessage *ais_msg)
2138 struct IdpClient *idp = cls;
2139 struct AttributeIterator *ai;
2141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2142 "Received ATTRIBUTE_ITERATION_START message\n");
2143 ai = GNUNET_new (struct AttributeIterator);
2144 ai->request_id = ntohl (ais_msg->id);
2146 ai->identity = ais_msg->identity;
2148 GNUNET_CONTAINER_DLL_insert (idp->op_head,
2151 bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
2152 GNUNET_SERVICE_client_continue (idp->client);
2157 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_STOP message
2159 * @param cls the client sending the message
2160 * @param ais_msg message from the client
2163 handle_iteration_stop (void *cls,
2164 const struct AttributeIterationStopMessage *ais_msg)
2166 struct IdpClient *idp = cls;
2167 struct AttributeIterator *ai;
2170 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2171 "Received `%s' message\n",
2172 "ATTRIBUTE_ITERATION_STOP");
2173 rid = ntohl (ais_msg->id);
2174 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2175 if (ai->request_id == rid)
2180 GNUNET_SERVICE_client_drop (idp->client);
2183 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2187 GNUNET_SERVICE_client_continue (idp->client);
2192 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT message
2194 * @param cls the client sending the message
2195 * @param message message from the client
2198 handle_iteration_next (void *cls,
2199 const struct AttributeIterationNextMessage *ais_msg)
2201 struct IdpClient *idp = cls;
2202 struct AttributeIterator *ai;
2205 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2206 "Received ATTRIBUTE_ITERATION_NEXT message\n");
2207 rid = ntohl (ais_msg->id);
2208 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2209 if (ai->request_id == rid)
2214 GNUNET_SERVICE_client_drop (idp->client);
2217 bootstrap_abe (&ai->identity,
2218 &iterate_next_after_abe_bootstrap,
2221 GNUNET_SERVICE_client_continue (idp->client);
2225 * Ticket iteration processor result
2227 enum ZoneIterationResult
2236 * Continue to iterate with next iteration_next call
2238 IT_SUCCESS_MORE_AVAILABLE = 1,
2241 * Iteration complete
2243 IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
2248 * Context for ticket iteration
2250 struct TicketIterationProcResult
2253 * The ticket iteration handle
2255 struct TicketIteration *ti;
2258 * Iteration result: iteration done?
2259 * #IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but
2260 * we got one for now and have sent it to the client
2261 * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
2262 * #IT_START: if we are still trying to find a result.
2264 int res_iteration_finished;
2269 cleanup_ticket_iter_handle (struct TicketIteration *ti)
2275 * Process ticket from database
2277 * @param cls struct TicketIterationProcResult
2278 * @param ticket the ticket
2279 * @param attrs the attributes
2282 ticket_iterate_proc (void *cls,
2283 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
2284 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
2286 struct TicketIterationProcResult *proc = cls;
2290 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2291 "Iteration done\n");
2292 proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2295 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
2296 send_ticket_result (proc->ti->client,
2304 * Perform ticket iteration step
2306 * @param ti ticket iterator to process
2309 run_ticket_iteration_round (struct TicketIteration *ti)
2311 struct TicketIterationProcResult proc;
2312 struct GNUNET_MQ_Envelope *env;
2313 struct TicketResultMessage *trm;
2316 memset (&proc, 0, sizeof (proc));
2318 proc.res_iteration_finished = IT_START;
2319 while (IT_START == proc.res_iteration_finished)
2321 if (GNUNET_SYSERR ==
2322 (ret = TKT_database->iterate_tickets (TKT_database->cls,
2326 &ticket_iterate_proc,
2332 if (GNUNET_NO == ret)
2333 proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2336 if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
2338 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2339 "More results available\n");
2340 return; /* more later */
2342 /* send empty response to indicate end of list */
2343 env = GNUNET_MQ_msg (trm,
2344 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
2345 trm->id = htonl (ti->r_id);
2346 GNUNET_MQ_send (ti->client->mq,
2348 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2349 ti->client->ticket_iter_tail,
2351 cleanup_ticket_iter_handle (ti);
2355 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START message
2357 * @param cls the client sending the message
2358 * @param tis_msg message from the client
2361 handle_ticket_iteration_start (void *cls,
2362 const struct TicketIterationStartMessage *tis_msg)
2364 struct IdpClient *client = cls;
2365 struct TicketIteration *ti;
2367 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2368 "Received TICKET_ITERATION_START message\n");
2369 ti = GNUNET_new (struct TicketIteration);
2370 ti->r_id = ntohl (tis_msg->id);
2372 ti->client = client;
2373 ti->identity = tis_msg->identity;
2374 ti->is_audience = ntohl (tis_msg->is_audience);
2376 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2377 client->ticket_iter_tail,
2379 run_ticket_iteration_round (ti);
2380 GNUNET_SERVICE_client_continue (client->client);
2385 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP message
2387 * @param cls the client sending the message
2388 * @param tis_msg message from the client
2391 handle_ticket_iteration_stop (void *cls,
2392 const struct TicketIterationStopMessage *tis_msg)
2394 struct IdpClient *client = cls;
2395 struct TicketIteration *ti;
2398 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2399 "Received `%s' message\n",
2400 "TICKET_ITERATION_STOP");
2401 rid = ntohl (tis_msg->id);
2402 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2403 if (ti->r_id == rid)
2408 GNUNET_SERVICE_client_drop (client->client);
2411 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2412 client->ticket_iter_tail,
2414 cleanup_ticket_iter_handle (ti);
2415 GNUNET_SERVICE_client_continue (client->client);
2420 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT message
2422 * @param cls the client sending the message
2423 * @param message message from the client
2426 handle_ticket_iteration_next (void *cls,
2427 const struct TicketIterationNextMessage *tis_msg)
2429 struct IdpClient *client = cls;
2430 struct TicketIteration *ti;
2433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2434 "Received TICKET_ITERATION_NEXT message\n");
2435 rid = ntohl (tis_msg->id);
2436 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2437 if (ti->r_id == rid)
2442 GNUNET_SERVICE_client_drop (client->client);
2445 run_ticket_iteration_round (ti);
2446 GNUNET_SERVICE_client_continue (client->client);
2453 * Main function that will be run
2455 * @param cls closure
2456 * @param args remaining command-line arguments
2457 * @param cfgfile name of the configuration file used (for saving, can be NULL)
2458 * @param c configuration
2462 const struct GNUNET_CONFIGURATION_Handle *c,
2463 struct GNUNET_SERVICE_Handle *server)
2468 stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
2470 //Connect to identity and namestore services
2471 ns_handle = GNUNET_NAMESTORE_connect (cfg);
2472 if (NULL == ns_handle)
2474 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
2477 gns_handle = GNUNET_GNS_connect (cfg);
2478 if (NULL == gns_handle)
2480 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
2482 credential_handle = GNUNET_CREDENTIAL_connect (cfg);
2483 if (NULL == credential_handle)
2485 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
2487 identity_handle = GNUNET_IDENTITY_connect (cfg,
2490 stats_handle = GNUNET_STATISTICS_create ("identity-provider",
2492 /* Loading DB plugin */
2494 GNUNET_CONFIGURATION_get_value_string (cfg,
2495 "identity-provider",
2498 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2499 "No database backend configured\n");
2500 GNUNET_asprintf (&db_lib_name,
2501 "libgnunet_plugin_identity_provider_%s",
2503 TKT_database = GNUNET_PLUGIN_load (db_lib_name,
2505 GNUNET_free (database);
2506 if (NULL == TKT_database)
2508 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2509 "Could not load database backend `%s'\n",
2511 GNUNET_SCHEDULER_shutdown ();
2516 GNUNET_CONFIGURATION_get_value_time (cfg,
2517 "identity-provider",
2518 "TOKEN_EXPIRATION_INTERVAL",
2519 &token_expiration_interval))
2521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2522 "Time window for zone iteration: %s\n",
2523 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
2526 token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
2529 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2533 * Called whenever a client is disconnected.
2535 * @param cls closure
2536 * @param client identification of the client
2537 * @param app_ctx @a client
2540 client_disconnect_cb (void *cls,
2541 struct GNUNET_SERVICE_Client *client,
2544 struct IdpClient *idp = app_ctx;
2545 struct AttributeIterator *ai;
2546 struct TicketIteration *ti;
2547 struct TicketRevocationHandle *rh;
2549 //TODO other operations
2551 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2552 "Client %p disconnected\n",
2555 while (NULL != (ai = idp->op_head))
2557 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2562 while (NULL != (rh = idp->revocation_list_head))
2564 GNUNET_CONTAINER_DLL_remove (idp->revocation_list_head,
2565 idp->revocation_list_tail,
2567 cleanup_revoke_ticket_handle (rh);
2569 while (NULL != (ti = idp->ticket_iter_head))
2571 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
2572 idp->ticket_iter_tail,
2574 cleanup_ticket_iter_handle (ti);
2581 * Add a client to our list of active clients.
2584 * @param client client to add
2585 * @param mq message queue for @a client
2586 * @return internal namestore client structure for this client
2589 client_connect_cb (void *cls,
2590 struct GNUNET_SERVICE_Client *client,
2591 struct GNUNET_MQ_Handle *mq)
2593 struct IdpClient *idp;
2594 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2595 "Client %p connected\n",
2597 idp = GNUNET_new (struct IdpClient);
2598 idp->client = client;
2606 * Define "main" method using service macro.
2609 ("identity-provider",
2610 GNUNET_SERVICE_OPTION_NONE,
2613 &client_disconnect_cb,
2615 GNUNET_MQ_hd_var_size (attribute_store_message,
2616 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
2617 struct AttributeStoreMessage,
2619 GNUNET_MQ_hd_fixed_size (iteration_start,
2620 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
2621 struct AttributeIterationStartMessage,
2623 GNUNET_MQ_hd_fixed_size (iteration_next,
2624 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
2625 struct AttributeIterationNextMessage,
2627 GNUNET_MQ_hd_fixed_size (iteration_stop,
2628 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
2629 struct AttributeIterationStopMessage,
2631 GNUNET_MQ_hd_var_size (issue_ticket_message,
2632 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET,
2633 struct IssueTicketMessage,
2635 GNUNET_MQ_hd_var_size (consume_ticket_message,
2636 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
2637 struct ConsumeTicketMessage,
2639 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
2640 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
2641 struct TicketIterationStartMessage,
2643 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2644 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
2645 struct TicketIterationNextMessage,
2647 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2648 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
2649 struct TicketIterationStopMessage,
2651 GNUNET_MQ_hd_var_size (revoke_ticket_message,
2652 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET,
2653 struct RevokeTicketMessage,
2655 GNUNET_MQ_handler_end());
2656 /* end of gnunet-service-identity-provider.c */