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_identity_provider_plugin.h"
37 #include "gnunet_signatures.h"
38 #include "identity_provider.h"
39 #include "identity_attribute.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;
69 static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database;
74 static char *db_lib_name;
77 * Token expiration interval
79 static struct GNUNET_TIME_Relative token_expiration_interval;
84 static struct GNUNET_NAMESTORE_Handle *ns_handle;
89 static struct GNUNET_GNS_Handle *gns_handle;
94 static struct GNUNET_CREDENTIAL_Handle *credential_handle;
99 static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
104 static struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
109 static struct GNUNET_SCHEDULER_Task *timeout_task;
114 static struct GNUNET_SCHEDULER_Task *update_task;
118 * Currently processed token
120 static struct IdentityToken *token;
123 * Label for currently processed token
128 * Scopes for processed token
133 * Handle to the statistics service.
135 static struct GNUNET_STATISTICS_Handle *stats;
140 static const struct GNUNET_CONFIGURATION_Handle *cfg;
148 * A ticket iteration operation.
150 struct TicketIteration
155 struct TicketIteration *next;
160 struct TicketIteration *prev;
163 * Client which intiated this zone iteration
165 struct IdpClient *client;
168 * Key of the identity we are iterating over.
170 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
173 * Identity is audience
175 uint32_t is_audience;
178 * The operation id fot the iteration in the response for the client
183 * Offset of the iteration used to address next result of the
184 * iteration in the store
186 * Initialy set to 0 in handle_iteration_start
187 * Incremented with by every call to handle_iteration_next
196 * Callback after an ABE bootstrap
199 * @param abe_key the ABE key that exists or was created
202 (*AbeBootstrapResult) (void *cls,
203 struct GNUNET_CRYPTO_AbeMasterKey *abe_key);
206 struct AbeBootstrapHandle
209 * Function to call when finished
211 AbeBootstrapResult proc;
219 * Key of the zone we are iterating over.
221 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
224 * Namestore Queue Entry
226 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
229 * The issuer egos ABE master key
231 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
235 * An attribute iteration operation.
237 struct AttributeIterator
240 * Next element in the DLL
242 struct AttributeIterator *next;
245 * Previous element in the DLL
247 struct AttributeIterator *prev;
250 * IDP client which intiated this zone iteration
252 struct IdpClient *client;
255 * Key of the zone we are iterating over.
257 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
260 * The issuer egos ABE master key
262 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
267 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
270 * The operation id fot the zone iteration in the response for the client
287 struct GNUNET_SERVICE_Client *client;
290 * Message queue for transmission to @e client
292 struct GNUNET_MQ_Handle *mq;
296 * Attribute iteration operations in
297 * progress initiated by this client
299 struct AttributeIterator *op_head;
303 * Attribute iteration operations
304 * in progress initiated by this client
306 struct AttributeIterator *op_tail;
309 * Head of DLL of ticket iteration ops
311 struct TicketIteration *ticket_iter_head;
314 * Tail of DLL of ticket iteration ops
316 struct TicketIteration *ticket_iter_tail;
320 * Head of DLL of ticket revocation ops
322 struct TicketRevocationHandle *revocation_list_head;
325 * Tail of DLL of ticket revocation ops
327 struct TicketRevocationHandle *revocation_list_tail;
332 struct AttributeStoreHandle
338 struct IdpClient *client;
343 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
348 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
351 * The issuer egos ABE master key
353 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
358 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
361 * The attribute to store
363 struct GNUNET_IDENTITY_PROVIDER_Attribute *attribute;
373 struct ParallelLookup;
375 struct ConsumeTicketHandle
381 struct IdpClient *client;
386 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
391 struct GNUNET_GNS_LookupRequest *lookup_request;
396 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
401 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
406 struct ParallelLookup *parallel_lookups_head;
411 struct ParallelLookup *parallel_lookups_tail;
416 struct GNUNET_SCHEDULER_Task *kill_task;
421 struct GNUNET_CRYPTO_AbeKey *key;
426 struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
436 * Handle for a parallel GNS lookup job
438 struct ParallelLookup
441 struct ParallelLookup *next;
444 struct ParallelLookup *prev;
446 /* The GNS request */
447 struct GNUNET_GNS_LookupRequest *lookup_request;
449 /* The handle the return to */
450 struct ConsumeTicketHandle *handle;
452 /* The label to look up */
457 * Ticket revocation request handle
459 struct TicketRevocationHandle
464 struct TicketRevocationHandle *next;
469 struct TicketRevocationHandle *prev;
474 struct IdpClient *client;
477 * Attributes to reissue
479 struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
482 * Attributes to revoke
484 struct GNUNET_IDENTITY_PROVIDER_AttributeList *rvk_attrs;
489 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
494 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
499 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
504 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
509 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
525 * Ticket issue request handle
527 struct TicketIssueHandle
533 struct IdpClient *client;
536 * Attributes to issue
538 struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
543 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
548 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
553 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
563 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
571 struct EgoEntry *next;
576 struct EgoEntry *prev;
581 struct GNUNET_IDENTITY_Ego *ego;
584 * Attribute map. Contains the attributes as json_t
586 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
596 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
600 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
603 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
605 GNUNET_free (db_lib_name);
607 if (NULL != timeout_task)
608 GNUNET_SCHEDULER_cancel (timeout_task);
609 if (NULL != update_task)
610 GNUNET_SCHEDULER_cancel (update_task);
611 if (NULL != identity_handle)
612 GNUNET_IDENTITY_disconnect (identity_handle);
613 if (NULL != gns_handle)
614 GNUNET_GNS_disconnect (gns_handle);
615 if (NULL != credential_handle)
616 GNUNET_CREDENTIAL_disconnect (credential_handle);
618 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
620 GNUNET_NAMESTORE_cancel (ns_qe);
621 if (NULL != ns_handle)
622 GNUNET_NAMESTORE_disconnect (ns_handle);
634 * @param tc task context
637 do_shutdown (void *cls)
639 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
640 "Shutting down...\n");
645 * Finished storing newly bootstrapped ABE key
648 bootstrap_store_cont (void *cls,
652 struct AbeBootstrapHandle *abh = cls;
653 if (GNUNET_SYSERR == success)
655 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
656 "Failed to bootstrap ABE master %s\n",
658 abh->proc (abh->proc_cls, NULL);
659 GNUNET_free (abh->abe_key);
663 abh->proc (abh->proc_cls, abh->abe_key);
668 * Generates and stores a new ABE key
671 bootstrap_store_task (void *cls)
673 struct AbeBootstrapHandle *abh = cls;
674 struct GNUNET_GNSRECORD_Data rd[1];
677 rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (abh->abe_key,
680 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
681 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
682 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
683 abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
688 &bootstrap_store_cont,
694 * Error checking for ABE master
697 bootstrap_abe_error (void *cls)
699 struct AbeBootstrapHandle *abh = cls;
701 abh->proc (abh->proc_cls, NULL);
707 * Handle ABE lookup in namestore
710 bootstrap_abe_result (void *cls,
711 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
713 unsigned int rd_count,
714 const struct GNUNET_GNSRECORD_Data *rd)
716 struct AbeBootstrapHandle *abh = cls;
717 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
720 for (i=0;i<rd_count;i++) {
721 if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
723 abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key (rd[i].data,
725 abh->proc (abh->proc_cls, abe_key);
730 //No ABE master found, bootstrapping...
731 abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
732 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
736 * Bootstrap ABE master if it does not yet exists.
737 * Will call the AbeBootstrapResult processor when done.
738 * will always recreate the ABE key of GNUNET_YES == recreate
741 bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
742 AbeBootstrapResult proc,
746 struct AbeBootstrapHandle *abh;
748 abh = GNUNET_new (struct AbeBootstrapHandle);
751 abh->identity = *identity;
752 if (GNUNET_YES == recreate)
754 abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
755 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
757 abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
760 &bootstrap_abe_error,
762 &bootstrap_abe_result,
770 create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
771 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
772 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
774 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
776 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
778 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
779 static const char ctx_key[] = "gnuid-aes-ctx-key";
780 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
781 new_key_hash, sizeof (struct GNUNET_HashCode),
782 ctx_key, strlen (ctx_key),
784 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
785 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
786 new_key_hash, sizeof (struct GNUNET_HashCode),
787 ctx_iv, strlen (ctx_iv),
793 cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
795 if (NULL != handle->attrs)
796 attribute_list_destroy (handle->attrs);
797 if (NULL != handle->ns_qe)
798 GNUNET_NAMESTORE_cancel (handle->ns_qe);
799 GNUNET_free (handle);
804 send_ticket_result (struct IdpClient *client,
806 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
807 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
809 struct TicketResultMessage *irm;
810 struct GNUNET_MQ_Envelope *env;
811 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
813 /* store ticket in DB */
814 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
818 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
819 "Unable to store ticket after issue\n");
823 env = GNUNET_MQ_msg_extra (irm,
824 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
825 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
826 ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
827 *ticket_buf = *ticket;
828 irm->id = htonl (r_id);
829 GNUNET_MQ_send (client->mq,
834 store_ticket_issue_cont (void *cls,
838 struct TicketIssueHandle *handle = cls;
840 handle->ns_qe = NULL;
841 if (GNUNET_SYSERR == success)
843 cleanup_ticket_issue_handle (handle);
844 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
846 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
849 send_ticket_result (handle->client,
853 cleanup_ticket_issue_handle (handle);
859 serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
860 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs,
861 const struct GNUNET_CRYPTO_AbeKey *rp_key,
862 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
865 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
866 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
868 char *serialized_key;
874 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
875 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
876 struct GNUNET_HashCode new_key_hash;
879 size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key,
880 (void**)&serialized_key);
882 for (le = attrs->list_head; NULL != le; le = le->next) {
883 attrs_str_len += strlen (le->attribute->name) + 1;
885 buf = GNUNET_malloc (attrs_str_len + size);
887 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
888 "Writing attributes\n");
889 for (le = attrs->list_head; NULL != le; le = le->next) {
890 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
891 "%s\n", le->attribute->name);
894 GNUNET_memcpy (write_ptr,
896 strlen (le->attribute->name));
897 write_ptr[strlen (le->attribute->name)] = ',';
898 write_ptr += strlen (le->attribute->name) + 1;
901 write_ptr[0] = '\0'; //replace last , with a 0-terminator
903 GNUNET_memcpy (write_ptr,
906 // ECDH keypair E = eG
907 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
908 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
910 enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
911 // Derived key K = H(eB)
912 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
915 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
916 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
917 size + attrs_str_len,
920 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
922 GNUNET_memcpy (*result,
924 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
925 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
928 GNUNET_free (enc_keyinfo);
930 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
936 issue_ticket_after_abe_bootstrap (void *cls,
937 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
939 struct TicketIssueHandle *ih = cls;
940 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
941 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
942 struct GNUNET_GNSRECORD_Data code_record[1];
943 struct GNUNET_CRYPTO_AbeKey *rp_key;
944 char *code_record_data;
949 size_t code_record_len;
951 //Create new ABE key for RP
953 for (le = ih->attrs->list_head; NULL != le; le = le->next)
955 attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
957 for (le = ih->attrs->list_head; NULL != le; le = le->next) {
958 attrs[i] = (char*) le->attribute->name;
962 rp_key = GNUNET_CRYPTO_cpabe_create_key (abe_key,
965 //TODO review this wireformat
966 code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
971 code_record[0].data = code_record_data;
972 code_record[0].data_size = code_record_len;
973 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
974 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
975 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
977 label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
980 ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
985 &store_ticket_issue_cont,
987 GNUNET_free (ecdhe_privkey);
990 GNUNET_free (code_record_data);
991 GNUNET_CRYPTO_cpabe_delete_master_key (abe_key);
992 GNUNET_CRYPTO_cpabe_delete_key (rp_key);
997 * Checks a ticket issue message
999 * @param cls client sending the message
1000 * @param im message of type `struct TicketIssueMessage`
1001 * @return #GNUNET_OK if @a im is well-formed
1004 check_issue_ticket_message(void *cls,
1005 const struct IssueTicketMessage *im)
1009 size = ntohs (im->header.size);
1010 if (size <= sizeof (struct IssueTicketMessage))
1013 return GNUNET_SYSERR;
1021 * Handler for ticket issue message
1024 * @param client who sent the message
1025 * @param message the message
1028 handle_issue_ticket_message (void *cls,
1029 const struct IssueTicketMessage *im)
1031 struct TicketIssueHandle *ih;
1032 struct IdpClient *idp = cls;
1035 ih = GNUNET_new (struct TicketIssueHandle);
1036 attrs_len = ntohs (im->attr_len);
1037 ih->attrs = attribute_list_deserialize ((char*)&im[1], attrs_len);
1038 ih->r_id = ntohl (im->id);
1040 ih->identity = im->identity;
1041 GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
1042 &ih->ticket.identity);
1043 ih->ticket.audience = im->rp;
1045 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1047 bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
1048 GNUNET_SERVICE_client_continue (idp->client);
1052 /**********************************************************
1054 **********************************************************/
1057 * Cleanup revoke handle
1060 cleanup_revoke_ticket_handle (struct TicketRevocationHandle *handle)
1062 if (NULL != handle->attrs)
1063 attribute_list_destroy (handle->attrs);
1064 if (NULL != handle->rvk_attrs)
1065 attribute_list_destroy (handle->rvk_attrs);
1066 if (NULL != handle->abe_key)
1067 GNUNET_CRYPTO_cpabe_delete_master_key (handle->abe_key);
1068 if (NULL != handle->ns_qe)
1069 GNUNET_NAMESTORE_cancel (handle->ns_qe);
1070 if (NULL != handle->ns_it)
1071 GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
1072 GNUNET_free (handle);
1077 * Send revocation result
1080 send_revocation_finished (struct TicketRevocationHandle *rh,
1083 struct GNUNET_MQ_Envelope *env;
1084 struct RevokeTicketResultMessage *trm;
1086 env = GNUNET_MQ_msg (trm,
1087 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT);
1088 trm->id = htonl (rh->r_id);
1089 trm->success = htonl (success);
1090 GNUNET_MQ_send (rh->client->mq,
1092 GNUNET_CONTAINER_DLL_remove (rh->client->revocation_list_head,
1093 rh->client->revocation_list_tail,
1099 * Process ticket from database
1101 * @param cls struct TicketIterationProcResult
1102 * @param ticket the ticket
1103 * @param attrs the attributes
1106 ticket_reissue_proc (void *cls,
1107 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1108 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs);
1112 reissue_ticket_cont (void *cls,
1116 struct TicketRevocationHandle *rh = cls;
1120 if (GNUNET_SYSERR == success)
1122 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1124 send_revocation_finished (rh, GNUNET_SYSERR);
1125 cleanup_revoke_ticket_handle (rh);
1128 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Continue DB iteration\n");
1130 GNUNET_assert (GNUNET_SYSERR != (ret =
1131 TKT_database->iterate_tickets (TKT_database->cls,
1132 &rh->ticket.identity,
1135 &ticket_reissue_proc,
1137 if (GNUNET_NO == ret)
1139 send_revocation_finished (rh, GNUNET_OK);
1140 cleanup_revoke_ticket_handle (rh);
1145 revocation_reissue_tickets (struct TicketRevocationHandle *rh);
1149 * Process ticket from database
1151 * @param cls struct TicketIterationProcResult
1152 * @param ticket the ticket
1153 * @param attrs the attributes
1156 ticket_reissue_proc (void *cls,
1157 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1158 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
1160 struct TicketRevocationHandle *rh = cls;
1161 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1162 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le_rollover;
1163 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
1164 struct GNUNET_GNSRECORD_Data code_record[1];
1165 struct GNUNET_CRYPTO_AbeKey *rp_key;
1166 char *code_record_data;
1173 size_t code_record_len;
1178 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1179 "Iteration done\n");
1180 send_revocation_finished (rh, GNUNET_OK);
1181 cleanup_revoke_ticket_handle (rh);
1186 * Check if any attribute of this ticket intersects with a rollover attribute
1188 reissue_ticket = GNUNET_NO;
1189 for (le = attrs->list_head; NULL != le; le = le->next)
1191 for (le_rollover = rh->rvk_attrs->list_head;
1192 NULL != le_rollover;
1193 le_rollover = le_rollover->next)
1195 if (0 == strcmp (le_rollover->attribute->name,
1196 le->attribute->name))
1198 reissue_ticket = GNUNET_YES;
1202 if (GNUNET_YES == reissue_ticket)
1206 if (GNUNET_NO == reissue_ticket)
1208 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1209 "Skipping ticket.\n");
1211 revocation_reissue_tickets (rh);
1215 //Create new ABE key for RP
1218 /* If this is the RP we want to revoke attributes of, the do so */
1220 for (le = attrs->list_head; NULL != le; le = le->next)
1222 attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1224 for (le = attrs->list_head; NULL != le; le = le->next) {
1225 GNUNET_asprintf (&policy, "%s:%lu",
1226 le->attribute->name,
1227 le->attribute->attribute_version);
1228 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1229 "Recreating key with %s\n", policy);
1230 attr_arr[i] = policy;
1234 rp_key = GNUNET_CRYPTO_cpabe_create_key (rh->abe_key,
1237 //TODO review this wireformat
1238 code_record_len = serialize_abe_keyinfo2 (&rh->ticket,
1243 code_record[0].data = code_record_data;
1244 code_record[0].data_size = code_record_len;
1245 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1246 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1247 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1249 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
1252 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1257 &reissue_ticket_cont,
1260 GNUNET_free (attr_arr[i-1]);
1261 GNUNET_free (ecdhe_privkey);
1262 GNUNET_free (label);
1263 GNUNET_free (attr_arr);
1264 GNUNET_free (code_record_data);
1265 GNUNET_CRYPTO_cpabe_delete_key (rp_key);
1269 /* Prototype for below function */
1271 attr_reenc_cont (void *cls,
1276 revocation_reissue_tickets (struct TicketRevocationHandle *rh)
1279 /* Done, issue new keys */
1280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1281 "Revocation Phase IV: Reissuing Tickets\n");
1282 if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
1283 &rh->ticket.identity,
1286 &ticket_reissue_proc,
1291 if (GNUNET_NO == ret)
1293 send_revocation_finished (rh, GNUNET_OK);
1294 cleanup_revoke_ticket_handle (rh);
1300 * Revoke next attribte by reencryption with
1304 reenc_next_attribute (struct TicketRevocationHandle *rh)
1306 struct GNUNET_GNSRECORD_Data rd[1];
1315 if (NULL == rh->attrs->list_head)
1317 revocation_reissue_tickets (rh);
1320 buf_size = attribute_serialize_get_size (rh->attrs->list_head->attribute);
1321 buf = GNUNET_malloc (buf_size);
1322 attribute_serialize (rh->attrs->list_head->attribute,
1324 rh->attrs->list_head->attribute->attribute_version++;
1325 GNUNET_asprintf (&policy, "%s:%lu",
1326 rh->attrs->list_head->attribute->name,
1327 rh->attrs->list_head->attribute->attribute_version);
1329 * Encrypt the attribute value and store in namestore
1331 enc_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1337 GNUNET_free (policy);
1338 rd[0].data_size = enc_size + sizeof (uint32_t);
1339 rd_buf = GNUNET_malloc (rd[0].data_size);
1340 attr_ver = htonl (rh->attrs->list_head->attribute->attribute_version);
1341 GNUNET_memcpy (rd_buf,
1344 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1347 rd[0].data = rd_buf;
1348 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1349 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1350 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1351 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1353 rh->attrs->list_head->attribute->name,
1358 GNUNET_free (enc_buf);
1359 GNUNET_free (rd_buf);
1363 * Namestore callback after revoked attribute
1367 attr_reenc_cont (void *cls,
1371 struct TicketRevocationHandle *rh = cls;
1372 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1374 if (GNUNET_SYSERR == success)
1376 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1377 "Failed to reencrypt attribute %s\n",
1379 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1382 if (NULL == rh->attrs->list_head)
1384 revocation_reissue_tickets (rh);
1387 le = rh->attrs->list_head;
1388 GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1389 rh->attrs->list_tail,
1391 GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
1392 rh->rvk_attrs->list_tail,
1396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1397 "Re-encrypting next attribute\n");
1398 reenc_next_attribute (rh);
1403 process_attributes_to_update (void *cls,
1404 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1405 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
1407 struct TicketRevocationHandle *rh = cls;
1409 rh->attrs = attribute_list_dup (attrs);
1410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1411 "Revocation Phase I: Collecting attributes\n");
1412 /* Reencrypt all attributes with new key */
1413 if (NULL == rh->attrs->list_head)
1415 /* No attributes to reencrypt */
1416 send_revocation_finished (rh, GNUNET_OK);
1417 cleanup_revoke_ticket_handle (rh);
1420 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1421 "Revocation Phase II: Re-encrypting attributes\n");
1422 reenc_next_attribute (rh);
1430 get_ticket_after_abe_bootstrap (void *cls,
1431 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1434 "Finished ABE bootstrap\n");
1435 struct TicketRevocationHandle *rh = cls;
1436 rh->abe_key = abe_key;
1437 TKT_database->get_ticket_attributes (TKT_database->cls,
1439 &process_attributes_to_update,
1444 * Checks a ticket revocation message
1446 * @param cls client sending the message
1447 * @param im message of type `struct RevokeTicketMessage`
1448 * @return #GNUNET_OK if @a im is well-formed
1451 check_revoke_ticket_message(void *cls,
1452 const struct RevokeTicketMessage *im)
1456 size = ntohs (im->header.size);
1457 if (size <= sizeof (struct RevokeTicketMessage))
1460 return GNUNET_SYSERR;
1466 * Handler for ticket revocation message
1469 * @param client who sent the message
1470 * @param message the message
1473 handle_revoke_ticket_message (void *cls,
1474 const struct RevokeTicketMessage *rm)
1476 struct TicketRevocationHandle *rh;
1477 struct IdpClient *idp = cls;
1478 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
1481 rh = GNUNET_new (struct TicketRevocationHandle);
1482 attrs_len = ntohs (rm->attrs_len);
1483 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1];
1485 rh->rvk_attrs = attribute_list_deserialize ((char*)&ticket[1], attrs_len);
1486 rh->rvk_attrs = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
1487 rh->ticket = *ticket;
1488 rh->r_id = ntohl (rm->id);
1490 rh->identity = rm->identity;
1491 GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
1492 &rh->ticket.identity);
1493 GNUNET_CONTAINER_DLL_insert (idp->revocation_list_head,
1494 idp->revocation_list_tail,
1496 bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO);
1497 GNUNET_SERVICE_client_continue (idp->client);
1503 cleanup_as_handle (struct AttributeStoreHandle *handle)
1505 if (NULL != handle->attribute)
1506 GNUNET_free (handle->attribute);
1507 if (NULL != handle->abe_key)
1508 GNUNET_CRYPTO_cpabe_delete_master_key (handle->abe_key);
1509 GNUNET_free (handle);
1513 * Checks a ticket consume message
1515 * @param cls client sending the message
1516 * @param im message of type `struct ConsumeTicketMessage`
1517 * @return #GNUNET_OK if @a im is well-formed
1520 check_consume_ticket_message(void *cls,
1521 const struct ConsumeTicketMessage *cm)
1525 size = ntohs (cm->header.size);
1526 if (size <= sizeof (struct ConsumeTicketMessage))
1529 return GNUNET_SYSERR;
1535 process_parallel_lookup2 (void *cls, uint32_t rd_count,
1536 const struct GNUNET_GNSRECORD_Data *rd)
1538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1539 "Parallel lookup finished (count=%u)\n", rd_count);
1540 struct ParallelLookup *parallel_lookup = cls;
1541 struct ConsumeTicketHandle *handle = parallel_lookup->handle;
1542 struct ConsumeTicketResultMessage *crm;
1543 struct GNUNET_MQ_Envelope *env;
1544 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *attr_le;
1550 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1551 handle->parallel_lookups_tail,
1553 GNUNET_free (parallel_lookup->label);
1554 GNUNET_free (parallel_lookup);
1556 GNUNET_break(0);//TODO
1557 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1559 attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data + sizeof (uint32_t),
1560 rd->data_size - sizeof (uint32_t),
1563 attr_le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
1564 attr_le->attribute = attribute_deserialize (data,
1566 attr_le->attribute->attribute_version = ntohl(*(uint32_t*)rd->data);
1567 GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
1568 handle->attrs->list_tail,
1572 if (NULL != handle->parallel_lookups_head)
1573 return; //Wait for more
1574 /* Else we are done */
1576 /* Store ticket in DB */
1577 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1581 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1582 "Unable to store ticket after consume\n");
1586 GNUNET_SCHEDULER_cancel (handle->kill_task);
1587 attrs_len = attribute_list_serialize_get_size (handle->attrs);
1588 env = GNUNET_MQ_msg_extra (crm,
1590 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
1591 crm->id = htonl (handle->r_id);
1592 crm->attrs_len = htons (attrs_len);
1593 crm->identity = handle->ticket.identity;
1594 data_tmp = (char *) &crm[1];
1595 attribute_list_serialize (handle->attrs,
1597 GNUNET_MQ_send (handle->client->mq, env);
1601 abort_parallel_lookups2 (void *cls)
1603 struct ConsumeTicketHandle *handle = cls;
1604 struct ParallelLookup *lu;
1605 struct ParallelLookup *tmp;
1606 struct AttributeResultMessage *arm;
1607 struct GNUNET_MQ_Envelope *env;
1609 for (lu = handle->parallel_lookups_head;
1611 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1612 GNUNET_free (lu->label);
1614 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1615 handle->parallel_lookups_tail,
1620 env = GNUNET_MQ_msg (arm,
1621 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1622 arm->id = htonl (handle->r_id);
1623 arm->attr_len = htons (0);
1624 GNUNET_MQ_send (handle->client->mq, env);
1629 cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
1631 if (NULL != handle->key)
1632 GNUNET_CRYPTO_cpabe_delete_key (handle->key);
1633 GNUNET_free (handle);
1638 process_consume_abe_key (void *cls, uint32_t rd_count,
1639 const struct GNUNET_GNSRECORD_Data *rd)
1641 struct ConsumeTicketHandle *handle = cls;
1642 struct GNUNET_HashCode new_key_hash;
1643 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1644 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1645 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1646 struct ParallelLookup *parallel_lookup;
1652 handle->lookup_request = NULL;
1655 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1656 "Number of keys %d != 1.",
1658 cleanup_consume_ticket_handle (handle);
1659 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1664 ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1666 buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1668 //Calculate symmetric key from ecdh parameters
1669 GNUNET_assert (GNUNET_OK ==
1670 GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
1673 create_sym_key_from_ecdh (&new_key_hash,
1676 size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1677 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1682 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1683 "Decrypted bytes: %zd Expected bytes: %zd\n",
1684 size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1686 scopes = GNUNET_strdup (buf);
1687 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1688 "Scopes %s\n", scopes);
1689 handle->key = GNUNET_CRYPTO_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1690 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1691 - strlen (scopes) - 1);
1693 for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1695 GNUNET_asprintf (&lookup_query,
1698 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1699 "Looking up %s\n", lookup_query);
1700 parallel_lookup = GNUNET_new (struct ParallelLookup);
1701 parallel_lookup->handle = handle;
1702 parallel_lookup->label = GNUNET_strdup (scope);
1703 parallel_lookup->lookup_request
1704 = GNUNET_GNS_lookup (gns_handle,
1706 &handle->ticket.identity,
1707 GNUNET_GNSRECORD_TYPE_ID_ATTR,
1708 GNUNET_GNS_LO_LOCAL_MASTER,
1709 &process_parallel_lookup2,
1711 GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1712 handle->parallel_lookups_tail,
1714 GNUNET_free (lookup_query);
1716 handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1717 &abort_parallel_lookups2,
1724 * Handler for ticket issue message
1727 * @param client who sent the message
1728 * @param message the message
1731 handle_consume_ticket_message (void *cls,
1732 const struct ConsumeTicketMessage *cm)
1734 struct ConsumeTicketHandle *ch;
1735 struct IdpClient *idp = cls;
1739 ch = GNUNET_new (struct ConsumeTicketHandle);
1740 ch->r_id = ntohl (cm->id);
1742 ch->identity = cm->identity;
1743 ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
1744 GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
1746 ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
1747 rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
1749 GNUNET_asprintf (&lookup_query,
1752 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1753 "Looking for ABE key under %s\n", lookup_query);
1756 = GNUNET_GNS_lookup (gns_handle,
1758 &ch->ticket.identity,
1759 GNUNET_GNSRECORD_TYPE_ABE_KEY,
1760 GNUNET_GNS_LO_LOCAL_MASTER,
1761 &process_consume_abe_key,
1763 GNUNET_free (rnd_label);
1764 GNUNET_free (lookup_query);
1765 GNUNET_SERVICE_client_continue (idp->client);
1769 attr_store_cont (void *cls,
1773 struct AttributeStoreHandle *as_handle = cls;
1774 struct GNUNET_MQ_Envelope *env;
1775 struct AttributeStoreResultMessage *acr_msg;
1777 if (GNUNET_SYSERR == success)
1779 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1780 "Failed to store attribute %s\n",
1782 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1786 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1787 "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1788 env = GNUNET_MQ_msg (acr_msg,
1789 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
1790 acr_msg->id = htonl (as_handle->r_id);
1791 acr_msg->op_result = htonl (GNUNET_OK);
1792 GNUNET_MQ_send (as_handle->client->mq,
1794 cleanup_as_handle (as_handle);
1798 attr_store_task (void *cls)
1800 struct AttributeStoreHandle *as_handle = cls;
1801 struct GNUNET_GNSRECORD_Data rd[1];
1810 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1811 "Storing attribute\n");
1812 buf_size = attribute_serialize_get_size (as_handle->attribute);
1813 buf = GNUNET_malloc (buf_size);
1815 attribute_serialize (as_handle->attribute,
1818 GNUNET_asprintf (&policy,
1820 as_handle->attribute->name,
1821 as_handle->attribute->attribute_version);
1823 * Encrypt the attribute value and store in namestore
1825 enc_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1831 GNUNET_free (policy);
1832 rd[0].data_size = enc_size + sizeof (uint32_t);
1833 rd_buf = GNUNET_malloc (rd[0].data_size);
1834 attr_ver = htonl (as_handle->attribute->attribute_version);
1835 GNUNET_memcpy (rd_buf,
1838 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1841 rd[0].data = rd_buf;
1842 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1843 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1844 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1845 as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1846 &as_handle->identity,
1847 as_handle->attribute->name,
1852 GNUNET_free (enc_buf);
1853 GNUNET_free (rd_buf);
1858 store_after_abe_bootstrap (void *cls,
1859 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1861 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1862 "Finished ABE bootstrap\n");
1863 struct AttributeStoreHandle *ash = cls;
1864 ash->abe_key = abe_key;
1865 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1869 * Checks a store message
1871 * @param cls client sending the message
1872 * @param sam message of type `struct AttributeStoreMessage`
1873 * @return #GNUNET_OK if @a im is well-formed
1876 check_attribute_store_message(void *cls,
1877 const struct AttributeStoreMessage *sam)
1881 size = ntohs (sam->header.size);
1882 if (size <= sizeof (struct AttributeStoreMessage))
1885 return GNUNET_SYSERR;
1893 * Handler for store message
1896 * @param client who sent the message
1897 * @param message the message
1900 handle_attribute_store_message (void *cls,
1901 const struct AttributeStoreMessage *sam)
1903 struct AttributeStoreHandle *as_handle;
1904 struct IdpClient *idp = cls;
1906 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1907 "Received ATTRIBUTE_STORE message\n");
1909 data_len = ntohs (sam->attr_len);
1911 as_handle = GNUNET_new (struct AttributeStoreHandle);
1912 as_handle->attribute = attribute_deserialize ((char*)&sam[1],
1915 as_handle->r_id = ntohl (sam->id);
1916 as_handle->identity = sam->identity;
1917 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1918 &as_handle->identity_pkey);
1920 GNUNET_SERVICE_client_continue (idp->client);
1921 as_handle->client = idp;
1922 bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
1926 cleanup_iter_handle (struct AttributeIterator *ai)
1928 if (NULL != ai->abe_key)
1929 GNUNET_free (ai->abe_key);
1930 GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
1931 ai->client->op_tail,
1937 attr_iter_error (void *cls)
1939 //struct AttributeIterator *ai = cls;
1941 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1942 "Failed to iterate over attributes\n");
1943 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1947 attr_iter_finished (void *cls)
1949 struct AttributeIterator *ai = cls;
1950 struct GNUNET_MQ_Envelope *env;
1951 struct AttributeResultMessage *arm;
1953 env = GNUNET_MQ_msg (arm,
1954 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1955 arm->id = htonl (ai->request_id);
1956 arm->attr_len = htons (0);
1957 GNUNET_MQ_send (ai->client->mq, env);
1958 cleanup_iter_handle (ai);
1962 attr_iter_cb (void *cls,
1963 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1965 unsigned int rd_count,
1966 const struct GNUNET_GNSRECORD_Data *rd)
1968 struct AttributeIterator *ai = cls;
1969 struct AttributeResultMessage *arm;
1970 struct GNUNET_CRYPTO_AbeKey *key;
1971 struct GNUNET_MQ_Envelope *env;
1972 ssize_t msg_extra_len;
1980 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1984 if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
1985 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1988 GNUNET_asprintf (&policy, "%s:%lu",
1989 label, *(uint32_t*)rd->data);
1992 key = GNUNET_CRYPTO_cpabe_create_key (ai->abe_key,
1994 msg_extra_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data+sizeof (uint32_t),
1995 rd->data_size-sizeof (uint32_t),
1998 GNUNET_CRYPTO_cpabe_delete_key (key);
1999 GNUNET_free (policy);
2000 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2001 "Found attribute: %s\n", label);
2002 env = GNUNET_MQ_msg_extra (arm,
2004 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
2005 arm->id = htonl (ai->request_id);
2006 arm->attr_len = htons (msg_extra_len);
2007 GNUNET_CRYPTO_ecdsa_key_get_public (zone,
2009 data_tmp = (char *) &arm[1];
2010 GNUNET_memcpy (data_tmp,
2013 GNUNET_MQ_send (ai->client->mq, env);
2014 GNUNET_free (attr_ser);
2019 iterate_after_abe_bootstrap (void *cls,
2020 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
2022 struct AttributeIterator *ai = cls;
2023 ai->abe_key = abe_key;
2024 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
2030 &attr_iter_finished,
2036 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_START message
2038 * @param cls the client sending the message
2039 * @param zis_msg message from the client
2042 handle_iteration_start (void *cls,
2043 const struct AttributeIterationStartMessage *ais_msg)
2045 struct IdpClient *idp = cls;
2046 struct AttributeIterator *ai;
2048 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2049 "Received ATTRIBUTE_ITERATION_START message\n");
2050 ai = GNUNET_new (struct AttributeIterator);
2051 ai->request_id = ntohl (ais_msg->id);
2053 ai->identity = ais_msg->identity;
2055 GNUNET_CONTAINER_DLL_insert (idp->op_head,
2058 bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
2059 GNUNET_SERVICE_client_continue (idp->client);
2064 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_STOP message
2066 * @param cls the client sending the message
2067 * @param ais_msg message from the client
2070 handle_iteration_stop (void *cls,
2071 const struct AttributeIterationStopMessage *ais_msg)
2073 struct IdpClient *idp = cls;
2074 struct AttributeIterator *ai;
2077 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2078 "Received `%s' message\n",
2079 "ATTRIBUTE_ITERATION_STOP");
2080 rid = ntohl (ais_msg->id);
2081 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2082 if (ai->request_id == rid)
2087 GNUNET_SERVICE_client_drop (idp->client);
2090 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2094 GNUNET_SERVICE_client_continue (idp->client);
2099 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT message
2101 * @param cls the client sending the message
2102 * @param message message from the client
2105 handle_iteration_next (void *cls,
2106 const struct AttributeIterationNextMessage *ais_msg)
2108 struct IdpClient *idp = cls;
2109 struct AttributeIterator *ai;
2112 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2113 "Received ATTRIBUTE_ITERATION_NEXT message\n");
2114 rid = ntohl (ais_msg->id);
2115 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2116 if (ai->request_id == rid)
2121 GNUNET_SERVICE_client_drop (idp->client);
2124 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2125 GNUNET_SERVICE_client_continue (idp->client);
2129 * Ticket iteration processor result
2131 enum ZoneIterationResult
2140 * Continue to iterate with next iteration_next call
2142 IT_SUCCESS_MORE_AVAILABLE = 1,
2145 * Iteration complete
2147 IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
2152 * Context for ticket iteration
2154 struct TicketIterationProcResult
2157 * The ticket iteration handle
2159 struct TicketIteration *ti;
2162 * Iteration result: iteration done?
2163 * #IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but
2164 * we got one for now and have sent it to the client
2165 * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
2166 * #IT_START: if we are still trying to find a result.
2168 int res_iteration_finished;
2173 cleanup_ticket_iter_handle (struct TicketIteration *ti)
2179 * Process ticket from database
2181 * @param cls struct TicketIterationProcResult
2182 * @param ticket the ticket
2183 * @param attrs the attributes
2186 ticket_iterate_proc (void *cls,
2187 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
2188 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
2190 struct TicketIterationProcResult *proc = cls;
2194 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2195 "Iteration done\n");
2196 proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2199 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
2200 send_ticket_result (proc->ti->client,
2208 * Perform ticket iteration step
2210 * @param ti ticket iterator to process
2213 run_ticket_iteration_round (struct TicketIteration *ti)
2215 struct TicketIterationProcResult proc;
2216 struct GNUNET_MQ_Envelope *env;
2217 struct TicketResultMessage *trm;
2220 memset (&proc, 0, sizeof (proc));
2222 proc.res_iteration_finished = IT_START;
2223 while (IT_START == proc.res_iteration_finished)
2225 if (GNUNET_SYSERR ==
2226 (ret = TKT_database->iterate_tickets (TKT_database->cls,
2230 &ticket_iterate_proc,
2236 if (GNUNET_NO == ret)
2237 proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2240 if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
2242 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2243 "More results available\n");
2244 return; /* more later */
2246 /* send empty response to indicate end of list */
2247 env = GNUNET_MQ_msg (trm,
2248 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
2249 trm->id = htonl (ti->r_id);
2250 GNUNET_MQ_send (ti->client->mq,
2252 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2253 ti->client->ticket_iter_tail,
2255 cleanup_ticket_iter_handle (ti);
2259 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START message
2261 * @param cls the client sending the message
2262 * @param tis_msg message from the client
2265 handle_ticket_iteration_start (void *cls,
2266 const struct TicketIterationStartMessage *tis_msg)
2268 struct IdpClient *client = cls;
2269 struct TicketIteration *ti;
2271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2272 "Received TICKET_ITERATION_START message\n");
2273 ti = GNUNET_new (struct TicketIteration);
2274 ti->r_id = ntohl (tis_msg->id);
2276 ti->client = client;
2277 ti->identity = tis_msg->identity;
2278 ti->is_audience = ntohl (tis_msg->is_audience);
2280 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2281 client->ticket_iter_tail,
2283 run_ticket_iteration_round (ti);
2284 GNUNET_SERVICE_client_continue (client->client);
2289 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP message
2291 * @param cls the client sending the message
2292 * @param tis_msg message from the client
2295 handle_ticket_iteration_stop (void *cls,
2296 const struct TicketIterationStopMessage *tis_msg)
2298 struct IdpClient *client = cls;
2299 struct TicketIteration *ti;
2302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2303 "Received `%s' message\n",
2304 "TICKET_ITERATION_STOP");
2305 rid = ntohl (tis_msg->id);
2306 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2307 if (ti->r_id == rid)
2312 GNUNET_SERVICE_client_drop (client->client);
2315 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2316 client->ticket_iter_tail,
2318 cleanup_ticket_iter_handle (ti);
2319 GNUNET_SERVICE_client_continue (client->client);
2324 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT message
2326 * @param cls the client sending the message
2327 * @param message message from the client
2330 handle_ticket_iteration_next (void *cls,
2331 const struct TicketIterationNextMessage *tis_msg)
2333 struct IdpClient *client = cls;
2334 struct TicketIteration *ti;
2337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2338 "Received TICKET_ITERATION_NEXT message\n");
2339 rid = ntohl (tis_msg->id);
2340 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2341 if (ti->r_id == rid)
2346 GNUNET_SERVICE_client_drop (client->client);
2349 run_ticket_iteration_round (ti);
2350 GNUNET_SERVICE_client_continue (client->client);
2357 * Main function that will be run
2359 * @param cls closure
2360 * @param args remaining command-line arguments
2361 * @param cfgfile name of the configuration file used (for saving, can be NULL)
2362 * @param c configuration
2366 const struct GNUNET_CONFIGURATION_Handle *c,
2367 struct GNUNET_SERVICE_Handle *server)
2372 stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
2374 //Connect to identity and namestore services
2375 ns_handle = GNUNET_NAMESTORE_connect (cfg);
2376 if (NULL == ns_handle)
2378 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
2381 gns_handle = GNUNET_GNS_connect (cfg);
2382 if (NULL == gns_handle)
2384 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
2386 credential_handle = GNUNET_CREDENTIAL_connect (cfg);
2387 if (NULL == credential_handle)
2389 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
2391 identity_handle = GNUNET_IDENTITY_connect (cfg,
2395 /* Loading DB plugin */
2397 GNUNET_CONFIGURATION_get_value_string (cfg,
2398 "identity-provider",
2401 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2402 "No database backend configured\n");
2403 GNUNET_asprintf (&db_lib_name,
2404 "libgnunet_plugin_identity_provider_%s",
2406 TKT_database = GNUNET_PLUGIN_load (db_lib_name,
2408 GNUNET_free (database);
2409 if (NULL == TKT_database)
2411 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2412 "Could not load database backend `%s'\n",
2414 GNUNET_SCHEDULER_shutdown ();
2419 GNUNET_CONFIGURATION_get_value_time (cfg,
2420 "identity-provider",
2421 "TOKEN_EXPIRATION_INTERVAL",
2422 &token_expiration_interval))
2424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2425 "Time window for zone iteration: %s\n",
2426 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
2429 token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
2432 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2436 * Called whenever a client is disconnected.
2438 * @param cls closure
2439 * @param client identification of the client
2440 * @param app_ctx @a client
2443 client_disconnect_cb (void *cls,
2444 struct GNUNET_SERVICE_Client *client,
2447 struct IdpClient *idp = app_ctx;
2448 struct AttributeIterator *ai;
2449 struct TicketIteration *ti;
2450 struct TicketRevocationHandle *rh;
2452 //TODO other operations
2454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2455 "Client %p disconnected\n",
2458 while (NULL != (ai = idp->op_head))
2460 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2465 while (NULL != (rh = idp->revocation_list_head))
2467 GNUNET_CONTAINER_DLL_remove (idp->revocation_list_head,
2468 idp->revocation_list_tail,
2470 cleanup_revoke_ticket_handle (rh);
2472 while (NULL != (ti = idp->ticket_iter_head))
2474 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
2475 idp->ticket_iter_tail,
2477 cleanup_ticket_iter_handle (ti);
2484 * Add a client to our list of active clients.
2487 * @param client client to add
2488 * @param mq message queue for @a client
2489 * @return internal namestore client structure for this client
2492 client_connect_cb (void *cls,
2493 struct GNUNET_SERVICE_Client *client,
2494 struct GNUNET_MQ_Handle *mq)
2496 struct IdpClient *idp;
2497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2498 "Client %p connected\n",
2500 idp = GNUNET_new (struct IdpClient);
2501 idp->client = client;
2509 * Define "main" method using service macro.
2512 ("identity-provider",
2513 GNUNET_SERVICE_OPTION_NONE,
2516 &client_disconnect_cb,
2518 GNUNET_MQ_hd_var_size (attribute_store_message,
2519 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
2520 struct AttributeStoreMessage,
2522 GNUNET_MQ_hd_fixed_size (iteration_start,
2523 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
2524 struct AttributeIterationStartMessage,
2526 GNUNET_MQ_hd_fixed_size (iteration_next,
2527 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
2528 struct AttributeIterationNextMessage,
2530 GNUNET_MQ_hd_fixed_size (iteration_stop,
2531 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
2532 struct AttributeIterationStopMessage,
2534 GNUNET_MQ_hd_var_size (issue_ticket_message,
2535 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET,
2536 struct IssueTicketMessage,
2538 GNUNET_MQ_hd_var_size (consume_ticket_message,
2539 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
2540 struct ConsumeTicketMessage,
2542 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
2543 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
2544 struct TicketIterationStartMessage,
2546 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2547 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
2548 struct TicketIterationNextMessage,
2550 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2551 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
2552 struct TicketIterationStopMessage,
2554 GNUNET_MQ_hd_var_size (revoke_ticket_message,
2555 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET,
2556 struct RevokeTicketMessage,
2558 GNUNET_MQ_handler_end());
2559 /* end of gnunet-service-identity-provider.c */