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;
435 * Handle for a parallel GNS lookup job
437 struct ParallelLookup
440 struct ParallelLookup *next;
443 struct ParallelLookup *prev;
445 /* The GNS request */
446 struct GNUNET_GNS_LookupRequest *lookup_request;
448 /* The handle the return to */
449 struct ConsumeTicketHandle *handle;
451 /* The label to look up */
456 * Ticket revocation request handle
458 struct TicketRevocationHandle
463 struct TicketRevocationHandle *next;
468 struct TicketRevocationHandle *prev;
473 struct IdpClient *client;
476 * Attributes to issue
478 struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
483 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
488 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
493 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
498 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
503 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
519 * Ticket issue request handle
521 struct TicketIssueHandle
527 struct IdpClient *client;
530 * Attributes to issue
532 struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
537 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
542 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
547 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
557 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
565 struct EgoEntry *next;
570 struct EgoEntry *prev;
575 struct GNUNET_IDENTITY_Ego *ego;
578 * Attribute map. Contains the attributes as json_t
580 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
590 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
594 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
597 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
599 GNUNET_free (db_lib_name);
601 if (NULL != timeout_task)
602 GNUNET_SCHEDULER_cancel (timeout_task);
603 if (NULL != update_task)
604 GNUNET_SCHEDULER_cancel (update_task);
605 if (NULL != identity_handle)
606 GNUNET_IDENTITY_disconnect (identity_handle);
607 if (NULL != gns_handle)
608 GNUNET_GNS_disconnect (gns_handle);
609 if (NULL != credential_handle)
610 GNUNET_CREDENTIAL_disconnect (credential_handle);
612 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
614 GNUNET_NAMESTORE_cancel (ns_qe);
615 if (NULL != ns_handle)
616 GNUNET_NAMESTORE_disconnect (ns_handle);
628 * @param tc task context
631 do_shutdown (void *cls)
633 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
634 "Shutting down...\n");
639 * Finished storing newly bootstrapped ABE key
642 bootstrap_store_cont (void *cls,
646 struct AbeBootstrapHandle *abh = cls;
647 if (GNUNET_SYSERR == success)
649 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
650 "Failed to bootstrap ABE master %s\n",
652 abh->proc (abh->proc_cls, NULL);
653 GNUNET_free (abh->abe_key);
657 abh->proc (abh->proc_cls, abh->abe_key);
662 * Generates and stores a new ABE key
665 bootstrap_store_task (void *cls)
667 struct AbeBootstrapHandle *abh = cls;
668 struct GNUNET_GNSRECORD_Data rd[1];
670 rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (abh->abe_key,
671 (void**)&rd[0].data);
672 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
673 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
674 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
675 abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
680 &bootstrap_store_cont,
685 * Error checking for ABE master
688 bootstrap_abe_error (void *cls)
690 struct AbeBootstrapHandle *abh = cls;
692 abh->proc (abh->proc_cls, NULL);
698 * Handle ABE lookup in namestore
701 bootstrap_abe_result (void *cls,
702 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
704 unsigned int rd_count,
705 const struct GNUNET_GNSRECORD_Data *rd)
707 struct AbeBootstrapHandle *abh = cls;
708 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
711 for (i=0;i<rd_count;i++) {
712 if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
714 abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key ((void**)rd[i].data,
716 abh->proc (abh->proc_cls, abe_key);
721 //No ABE master found, bootstrapping...
722 abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
723 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
727 * Bootstrap ABE master if it does not yet exists.
728 * Will call the AbeBootstrapResult processor when done.
729 * will always recreate the ABE key of GNUNET_YES == recreate
732 bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
733 AbeBootstrapResult proc,
737 struct AbeBootstrapHandle *abh;
739 abh = GNUNET_new (struct AbeBootstrapHandle);
742 abh->identity = *identity;
743 if (GNUNET_YES == recreate)
745 abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
746 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
748 abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
751 &bootstrap_abe_error,
753 &bootstrap_abe_result,
761 create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
762 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
763 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
765 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
767 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
769 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
770 static const char ctx_key[] = "gnuid-aes-ctx-key";
771 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
772 new_key_hash, sizeof (struct GNUNET_HashCode),
773 ctx_key, strlen (ctx_key),
775 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
776 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
777 new_key_hash, sizeof (struct GNUNET_HashCode),
778 ctx_iv, strlen (ctx_iv),
784 cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
786 if (NULL != handle->attrs)
787 attribute_list_destroy (handle->attrs);
788 if (NULL != handle->ns_qe)
789 GNUNET_NAMESTORE_cancel (handle->ns_qe);
790 GNUNET_free (handle);
795 send_ticket_result (struct IdpClient *client,
797 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
798 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
800 struct TicketResultMessage *irm;
801 struct GNUNET_MQ_Envelope *env;
802 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
804 /* store ticket in DB */
805 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
809 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
810 "Unable to store ticket after issue\n");
814 env = GNUNET_MQ_msg_extra (irm,
815 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
816 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
817 ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
818 *ticket_buf = *ticket;
819 irm->id = htonl (r_id);
820 GNUNET_MQ_send (client->mq,
825 store_ticket_issue_cont (void *cls,
829 struct TicketIssueHandle *handle = cls;
831 handle->ns_qe = NULL;
832 if (GNUNET_SYSERR == success)
834 cleanup_ticket_issue_handle (handle);
835 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
837 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
840 send_ticket_result (handle->client,
844 cleanup_ticket_issue_handle (handle);
850 serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
851 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs,
852 const struct GNUNET_CRYPTO_AbeKey *rp_key,
853 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
856 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
857 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
859 char *serialized_key;
865 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
866 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
867 struct GNUNET_HashCode new_key_hash;
870 size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key,
871 (void**)&serialized_key);
873 for (le = attrs->list_head; NULL != le; le = le->next) {
874 attrs_str_len += strlen (le->attribute->name) + 1;
876 buf = GNUNET_malloc (attrs_str_len + size);
878 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
879 "Writing attributes\n");
880 for (le = attrs->list_head; NULL != le; le = le->next) {
881 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
882 "%s\n", le->attribute->name);
885 GNUNET_memcpy (write_ptr,
887 strlen (le->attribute->name));
888 write_ptr[strlen (le->attribute->name)] = ',';
889 write_ptr += strlen (le->attribute->name) + 1;
892 write_ptr[0] = '\0'; //replace last , with a 0-terminator
894 GNUNET_memcpy (write_ptr,
897 // ECDH keypair E = eG
898 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
899 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
901 enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
902 // Derived key K = H(eB)
903 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
906 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
907 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
908 size + attrs_str_len,
911 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
913 GNUNET_memcpy (*result,
915 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
916 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
919 GNUNET_free (enc_keyinfo);
920 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
926 issue_ticket_after_abe_bootstrap (void *cls,
927 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
929 struct TicketIssueHandle *ih = cls;
930 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
931 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
932 struct GNUNET_GNSRECORD_Data code_record[1];
933 struct GNUNET_CRYPTO_AbeKey *rp_key;
934 char *code_record_data;
939 size_t code_record_len;
941 //Create new ABE key for RP
943 for (le = ih->attrs->list_head; NULL != le; le = le->next)
945 attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
947 for (le = ih->attrs->list_head; NULL != le; le = le->next) {
948 attrs[i] = (char*) le->attribute->name;
952 rp_key = GNUNET_CRYPTO_cpabe_create_key (abe_key,
955 //TODO review this wireformat
956 code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
961 code_record[0].data = code_record_data;
962 code_record[0].data_size = code_record_len;
963 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
964 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
965 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
967 label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
970 ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
975 &store_ticket_issue_cont,
977 GNUNET_free (ecdhe_privkey);
980 GNUNET_free (code_record_data);
985 * Checks a ticket issue message
987 * @param cls client sending the message
988 * @param im message of type `struct TicketIssueMessage`
989 * @return #GNUNET_OK if @a im is well-formed
992 check_issue_ticket_message(void *cls,
993 const struct IssueTicketMessage *im)
997 size = ntohs (im->header.size);
998 if (size <= sizeof (struct IssueTicketMessage))
1001 return GNUNET_SYSERR;
1009 * Handler for ticket issue message
1012 * @param client who sent the message
1013 * @param message the message
1016 handle_issue_ticket_message (void *cls,
1017 const struct IssueTicketMessage *im)
1019 struct TicketIssueHandle *ih;
1020 struct IdpClient *idp = cls;
1023 ih = GNUNET_new (struct TicketIssueHandle);
1024 attrs_len = ntohs (im->attr_len);
1025 ih->attrs = attribute_list_deserialize ((char*)&im[1], attrs_len);
1026 ih->r_id = ntohl (im->id);
1028 ih->identity = im->identity;
1029 GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
1030 &ih->ticket.identity);
1031 ih->ticket.audience = im->rp;
1033 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1035 bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
1036 GNUNET_SERVICE_client_continue (idp->client);
1040 /**********************************************************
1042 **********************************************************/
1045 * Cleanup revoke handle
1048 cleanup_revoke_ticket_handle (struct TicketRevocationHandle *handle)
1050 if (NULL != handle->attrs)
1051 attribute_list_destroy (handle->attrs);
1052 if (NULL != handle->abe_key)
1053 GNUNET_free (handle->abe_key);
1054 if (NULL != handle->ns_qe)
1055 GNUNET_NAMESTORE_cancel (handle->ns_qe);
1056 if (NULL != handle->ns_it)
1057 GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
1058 GNUNET_free (handle);
1063 * Send revocation result
1066 send_revocation_finished (struct TicketRevocationHandle *rh,
1069 struct GNUNET_MQ_Envelope *env;
1070 struct RevokeTicketResultMessage *trm;
1072 env = GNUNET_MQ_msg (trm,
1073 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT);
1074 trm->id = htonl (rh->r_id);
1075 trm->success = htonl (success);
1076 GNUNET_MQ_send (rh->client->mq,
1078 GNUNET_CONTAINER_DLL_remove (rh->client->revocation_list_head,
1079 rh->client->revocation_list_tail,
1081 cleanup_revoke_ticket_handle (rh);
1086 * Process ticket from database
1088 * @param cls struct TicketIterationProcResult
1089 * @param ticket the ticket
1090 * @param attrs the attributes
1093 ticket_reissue_proc (void *cls,
1094 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1095 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs);
1099 reissue_ticket_cont (void *cls,
1103 struct TicketRevocationHandle *rh = cls;
1106 if (GNUNET_SYSERR == success)
1108 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1110 send_revocation_finished (rh, GNUNET_SYSERR);
1111 cleanup_revoke_ticket_handle (rh);
1115 GNUNET_assert (GNUNET_SYSERR !=
1116 TKT_database->iterate_tickets (TKT_database->cls,
1117 &rh->ticket.identity,
1120 &ticket_reissue_proc,
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_PROVIDER_AttributeList *attrs)
1138 struct TicketRevocationHandle *rh = cls;
1139 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs_to_reissue;
1140 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1141 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
1142 struct GNUNET_GNSRECORD_Data code_record[1];
1143 struct GNUNET_CRYPTO_AbeKey *rp_key;
1144 char *code_record_data;
1149 size_t code_record_len;
1154 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1155 "Iteration done\n");
1156 send_revocation_finished (rh, GNUNET_OK);
1157 cleanup_revoke_ticket_handle (rh);
1160 //Create new ABE key for RP
1162 attrs_to_reissue = attrs;
1164 /* If this is the RP we want to revoke attributes of, the do so */
1165 if (0 == memcmp (&ticket->audience,
1166 &rh->ticket.audience,
1167 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
1168 attrs_to_reissue = rh->attrs;
1170 for (le = attrs_to_reissue->list_head; NULL != le; le = le->next)
1172 attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1174 for (le = attrs_to_reissue->list_head; NULL != le; le = le->next) {
1175 attr_arr[i] = (char*) le->attribute->name;
1179 rp_key = GNUNET_CRYPTO_cpabe_create_key (rh->abe_key,
1182 //TODO review this wireformat
1183 code_record_len = serialize_abe_keyinfo2 (&rh->ticket,
1188 code_record[0].data = code_record_data;
1189 code_record[0].data_size = code_record_len;
1190 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1191 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1192 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1194 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
1197 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1202 &reissue_ticket_cont,
1204 GNUNET_free (ecdhe_privkey);
1205 GNUNET_free (label);
1206 GNUNET_free (attr_arr);
1207 GNUNET_free (code_record_data);
1214 /* Prototype for below function */
1216 attr_reenc_cont (void *cls,
1221 * Revoke next attribte by reencryption with
1225 reenc_next_attribute (struct TicketRevocationHandle *rh)
1227 struct GNUNET_GNSRECORD_Data rd[1];
1231 buf_size = attribute_serialize_get_size (rh->attrs->list_head->attribute);
1232 buf = GNUNET_malloc (buf_size);
1234 attribute_serialize (rh->attrs->list_head->attribute,
1238 * Encrypt the attribute value and store in namestore
1240 rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1242 rh->attrs->list_head->attribute->name, //Policy
1244 (void**)&rd[0].data);
1246 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1247 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1248 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1249 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1251 rh->attrs->list_head->attribute->name,
1256 GNUNET_free ((void*)rd[0].data);
1261 * Namestore callback after revoked attribute
1265 attr_reenc_cont (void *cls,
1269 struct TicketRevocationHandle *rh = cls;
1270 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1273 if (GNUNET_SYSERR == success)
1275 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1276 "Failed to reencrypt attribute %s\n",
1278 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1281 le = rh->attrs->list_head;
1282 GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1283 rh->attrs->list_tail,
1284 rh->attrs->list_head);
1285 GNUNET_free (le->attribute);
1288 if (NULL == rh->attrs->list_head)
1290 /* Done, issue new keys */
1291 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1292 "Revocation Phase IV: Reissuing Tickets\n");
1293 if (GNUNET_SYSERR ==
1294 (ret = TKT_database->iterate_tickets (TKT_database->cls,
1295 &rh->ticket.identity,
1298 &ticket_reissue_proc,
1305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1306 "Re-encrypting next attribute\n");
1307 reenc_next_attribute (rh);
1312 * Start reencryption with newly generated ABE master
1315 reenc_after_abe_bootstrap (void *cls,
1316 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1318 struct TicketRevocationHandle *rh = cls;
1319 GNUNET_free (rh->abe_key);
1320 GNUNET_assert (NULL != abe_key);
1321 rh->abe_key = abe_key;
1323 if (NULL == rh->attrs->list_head)
1325 /* No attributes to reencrypt */
1326 send_revocation_finished (rh, GNUNET_OK);
1327 cleanup_revoke_ticket_handle (rh);
1330 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1331 "Revocation Phase III: Re-encrypting attributes\n");
1332 reenc_next_attribute (rh);
1338 * Collecting attributes failed... abort.
1341 revoke_collect_iter_error (void *cls)
1343 struct TicketRevocationHandle *rh = cls;
1345 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1346 "Failed to iterate over attributes\n");
1348 send_revocation_finished (rh, GNUNET_SYSERR);
1349 cleanup_revoke_ticket_handle (rh);
1353 * Done decrypting existing attributes.
1356 revoke_collect_iter_finished (void *cls)
1358 struct TicketRevocationHandle *rh = cls;
1360 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1361 "Revocation Phase II: Invalidating old ABE Master\n");
1362 /* Bootstrap new abe key */
1363 bootstrap_abe (&rh->identity, &reenc_after_abe_bootstrap, rh, GNUNET_YES);
1367 * Decrypt existing attribute and store it
1368 * We will revoke it by reencrypting it with a new ABE master key.
1371 revoke_collect_iter_cb (void *cls,
1372 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1374 unsigned int rd_count,
1375 const struct GNUNET_GNSRECORD_Data *rd)
1377 struct TicketRevocationHandle *rh = cls;
1378 struct GNUNET_CRYPTO_AbeKey *key;
1379 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1386 GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it);
1390 if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
1391 GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it);
1394 attrs[0] = (char*)label;
1396 key = GNUNET_CRYPTO_cpabe_create_key (rh->abe_key,
1398 attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
1402 GNUNET_CRYPTO_cpabe_delete_key (key);
1403 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1404 "Attribute to reencrypt: %s\n", label);
1405 le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
1406 le->attribute = attribute_deserialize (attr_ser, attr_len);
1407 GNUNET_CONTAINER_DLL_insert_tail (rh->attrs->list_head,
1408 rh->attrs->list_tail,
1410 GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it);
1414 * Start attribute collection for revocation
1417 collect_after_abe_bootstrap (void *cls,
1418 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1420 struct TicketRevocationHandle *rh = cls;
1423 GNUNET_assert (NULL != abe_key);
1424 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1425 "Revocation Phase I: Collecting attributes\n");
1426 /* Reencrypt all attributes with new key */
1427 rh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1429 &revoke_collect_iter_error,
1431 &revoke_collect_iter_cb,
1433 &revoke_collect_iter_finished,
1440 * Checks a ticket revocation message
1442 * @param cls client sending the message
1443 * @param im message of type `struct RevokeTicketMessage`
1444 * @return #GNUNET_OK if @a im is well-formed
1447 check_revoke_ticket_message(void *cls,
1448 const struct RevokeTicketMessage *im)
1452 size = ntohs (im->header.size);
1453 if (size <= sizeof (struct RevokeTicketMessage))
1456 return GNUNET_SYSERR;
1464 * Handler for ticket revocation message
1467 * @param client who sent the message
1468 * @param message the message
1471 handle_revoke_ticket_message (void *cls,
1472 const struct RevokeTicketMessage *rm)
1474 struct TicketRevocationHandle *rh;
1475 struct IdpClient *idp = cls;
1476 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
1479 rh = GNUNET_new (struct TicketRevocationHandle);
1480 attrs_len = ntohs (rm->attrs_len);
1481 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1];
1483 rh->attrs = attribute_list_deserialize ((char*)&ticket[1], attrs_len);
1484 rh->ticket = *ticket;
1485 rh->r_id = ntohl (rm->id);
1487 rh->identity = rm->identity;
1488 GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
1489 &rh->ticket.identity);
1490 GNUNET_CONTAINER_DLL_insert (idp->revocation_list_head,
1491 idp->revocation_list_tail,
1493 bootstrap_abe (&rh->identity, &collect_after_abe_bootstrap, rh, GNUNET_NO);
1494 GNUNET_SERVICE_client_continue (idp->client);
1500 cleanup_as_handle (struct AttributeStoreHandle *handle)
1502 if (NULL != handle->attribute)
1503 GNUNET_free (handle->attribute);
1504 if (NULL != handle->abe_key)
1505 GNUNET_free (handle->abe_key);
1506 GNUNET_free (handle);
1510 * Checks a ticket consume message
1512 * @param cls client sending the message
1513 * @param im message of type `struct ConsumeTicketMessage`
1514 * @return #GNUNET_OK if @a im is well-formed
1517 check_consume_ticket_message(void *cls,
1518 const struct ConsumeTicketMessage *cm)
1522 size = ntohs (cm->header.size);
1523 if (size <= sizeof (struct ConsumeTicketMessage))
1526 return GNUNET_SYSERR;
1532 process_parallel_lookup2 (void *cls, uint32_t rd_count,
1533 const struct GNUNET_GNSRECORD_Data *rd)
1535 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1536 "Parallel lookup finished (count=%u)\n", rd_count);
1537 struct ParallelLookup *parallel_lookup = cls;
1538 struct ConsumeTicketHandle *handle = parallel_lookup->handle;
1539 struct ConsumeTicketResultMessage *crm;
1540 struct GNUNET_MQ_Envelope *env;
1541 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *attr_le;
1547 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1548 handle->parallel_lookups_tail,
1550 GNUNET_free (parallel_lookup->label);
1551 GNUNET_free (parallel_lookup);
1553 GNUNET_break(0);//TODO
1554 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1556 attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
1560 attr_le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
1561 attr_le->attribute = attribute_deserialize (data,
1563 GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
1564 handle->attrs->list_tail,
1568 if (NULL != handle->parallel_lookups_head)
1569 return; //Wait for more
1570 /* Else we are done */
1572 /* Store ticket in DB */
1573 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1577 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1578 "Unable to store ticket after consume\n");
1582 GNUNET_SCHEDULER_cancel (handle->kill_task);
1583 attrs_len = attribute_list_serialize_get_size (handle->attrs);
1584 env = GNUNET_MQ_msg_extra (crm,
1586 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
1587 crm->id = htonl (handle->r_id);
1588 crm->attrs_len = htons (attrs_len);
1589 crm->identity = handle->ticket.identity;
1590 data_tmp = (char *) &crm[1];
1591 attribute_list_serialize (handle->attrs,
1593 GNUNET_MQ_send (handle->client->mq, env);
1597 abort_parallel_lookups2 (void *cls)
1599 struct ConsumeTicketHandle *handle = cls;
1600 struct ParallelLookup *lu;
1601 struct ParallelLookup *tmp;
1602 struct AttributeResultMessage *arm;
1603 struct GNUNET_MQ_Envelope *env;
1605 for (lu = handle->parallel_lookups_head;
1607 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1608 GNUNET_free (lu->label);
1610 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1611 handle->parallel_lookups_tail,
1616 env = GNUNET_MQ_msg (arm,
1617 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1618 arm->id = htonl (handle->r_id);
1619 arm->attr_len = htons (0);
1620 GNUNET_MQ_send (handle->client->mq, env);
1625 cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
1627 if (NULL != handle->key)
1628 GNUNET_free (handle->key);
1629 GNUNET_free (handle);
1634 process_consume_abe_key (void *cls, uint32_t rd_count,
1635 const struct GNUNET_GNSRECORD_Data *rd)
1637 struct ConsumeTicketHandle *handle = cls;
1638 struct GNUNET_HashCode new_key_hash;
1639 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1640 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1641 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1642 struct ParallelLookup *parallel_lookup;
1648 handle->lookup_request = NULL;
1651 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1652 "Number of keys %d != 1.",
1654 cleanup_consume_ticket_handle (handle);
1655 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1660 ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1662 buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1664 //Calculate symmetric key from ecdh parameters
1665 GNUNET_assert (GNUNET_OK ==
1666 GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
1669 create_sym_key_from_ecdh (&new_key_hash,
1672 size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1673 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1679 "Decrypted bytes: %zd Expected bytes: %zd\n",
1680 size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1682 scopes = GNUNET_strdup (buf);
1683 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1684 "Scopes %s\n", scopes);
1685 handle->key = GNUNET_CRYPTO_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1686 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1687 - strlen (scopes) - 1);
1689 for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1691 GNUNET_asprintf (&lookup_query,
1694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1695 "Looking up %s\n", lookup_query);
1696 parallel_lookup = GNUNET_new (struct ParallelLookup);
1697 parallel_lookup->handle = handle;
1698 parallel_lookup->label = GNUNET_strdup (scope);
1699 parallel_lookup->lookup_request
1700 = GNUNET_GNS_lookup (gns_handle,
1702 &handle->ticket.identity,
1703 GNUNET_GNSRECORD_TYPE_ID_ATTR,
1704 GNUNET_GNS_LO_LOCAL_MASTER,
1705 &process_parallel_lookup2,
1707 GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1708 handle->parallel_lookups_tail,
1710 GNUNET_free (lookup_query);
1712 handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1713 &abort_parallel_lookups2,
1720 * Handler for ticket issue message
1723 * @param client who sent the message
1724 * @param message the message
1727 handle_consume_ticket_message (void *cls,
1728 const struct ConsumeTicketMessage *cm)
1730 struct ConsumeTicketHandle *ch;
1731 struct IdpClient *idp = cls;
1735 ch = GNUNET_new (struct ConsumeTicketHandle);
1736 ch->r_id = ntohl (cm->id);
1738 ch->identity = cm->identity;
1739 ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
1740 GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
1742 ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
1743 rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
1745 GNUNET_asprintf (&lookup_query,
1748 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1749 "Looking for ABE key under %s\n", lookup_query);
1752 = GNUNET_GNS_lookup (gns_handle,
1754 &ch->ticket.identity,
1755 GNUNET_GNSRECORD_TYPE_ABE_KEY,
1756 GNUNET_GNS_LO_LOCAL_MASTER,
1757 &process_consume_abe_key,
1759 GNUNET_free (rnd_label);
1760 GNUNET_free (lookup_query);
1761 GNUNET_SERVICE_client_continue (idp->client);
1765 attr_store_cont (void *cls,
1769 struct AttributeStoreHandle *as_handle = cls;
1770 struct GNUNET_MQ_Envelope *env;
1771 struct AttributeStoreResultMessage *acr_msg;
1773 if (GNUNET_SYSERR == success)
1775 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1776 "Failed to store attribute %s\n",
1778 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1782 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1783 "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1784 env = GNUNET_MQ_msg (acr_msg,
1785 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
1786 acr_msg->id = htonl (as_handle->r_id);
1787 acr_msg->op_result = htonl (GNUNET_OK);
1788 GNUNET_MQ_send (as_handle->client->mq,
1790 cleanup_as_handle (as_handle);
1794 attr_store_task (void *cls)
1796 struct AttributeStoreHandle *as_handle = cls;
1797 struct GNUNET_GNSRECORD_Data rd[1];
1801 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1802 "Storing attribute\n");
1803 buf_size = attribute_serialize_get_size (as_handle->attribute);
1804 buf = GNUNET_malloc (buf_size);
1806 attribute_serialize (as_handle->attribute,
1810 * Encrypt the attribute value and store in namestore
1812 rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1814 as_handle->attribute->name, //Policy
1816 (void**)&rd[0].data);
1818 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1819 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1820 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1821 as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1822 &as_handle->identity,
1823 as_handle->attribute->name,
1828 GNUNET_free ((void*)rd[0].data);
1834 store_after_abe_bootstrap (void *cls,
1835 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1837 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1838 "Finished ABE bootstrap\n");
1839 struct AttributeStoreHandle *ash = cls;
1840 ash->abe_key = abe_key;
1841 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1845 * Checks a store message
1847 * @param cls client sending the message
1848 * @param sam message of type `struct AttributeStoreMessage`
1849 * @return #GNUNET_OK if @a im is well-formed
1852 check_attribute_store_message(void *cls,
1853 const struct AttributeStoreMessage *sam)
1857 size = ntohs (sam->header.size);
1858 if (size <= sizeof (struct AttributeStoreMessage))
1861 return GNUNET_SYSERR;
1869 * Handler for store message
1872 * @param client who sent the message
1873 * @param message the message
1876 handle_attribute_store_message (void *cls,
1877 const struct AttributeStoreMessage *sam)
1879 struct AttributeStoreHandle *as_handle;
1880 struct IdpClient *idp = cls;
1882 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1883 "Received ATTRIBUTE_STORE message\n");
1885 data_len = ntohs (sam->attr_len);
1887 as_handle = GNUNET_new (struct AttributeStoreHandle);
1888 as_handle->attribute = attribute_deserialize ((char*)&sam[1],
1891 as_handle->r_id = ntohl (sam->id);
1892 as_handle->identity = sam->identity;
1893 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1894 &as_handle->identity_pkey);
1896 GNUNET_SERVICE_client_continue (idp->client);
1897 as_handle->client = idp;
1898 bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
1902 cleanup_iter_handle (struct AttributeIterator *ai)
1904 if (NULL != ai->abe_key)
1905 GNUNET_free (ai->abe_key);
1906 GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
1907 ai->client->op_tail,
1913 attr_iter_error (void *cls)
1915 //struct AttributeIterator *ai = cls;
1917 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1918 "Failed to iterate over attributes\n");
1919 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1923 attr_iter_finished (void *cls)
1925 struct AttributeIterator *ai = cls;
1926 struct GNUNET_MQ_Envelope *env;
1927 struct AttributeResultMessage *arm;
1929 env = GNUNET_MQ_msg (arm,
1930 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1931 arm->id = htonl (ai->request_id);
1932 arm->attr_len = htons (0);
1933 GNUNET_MQ_send (ai->client->mq, env);
1934 cleanup_iter_handle (ai);
1938 attr_iter_cb (void *cls,
1939 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1941 unsigned int rd_count,
1942 const struct GNUNET_GNSRECORD_Data *rd)
1944 struct AttributeIterator *ai = cls;
1945 struct AttributeResultMessage *arm;
1946 struct GNUNET_CRYPTO_AbeKey *key;
1947 struct GNUNET_MQ_Envelope *env;
1948 ssize_t msg_extra_len;
1955 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1959 if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
1960 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1963 attrs[0] = (char*)label;
1965 key = GNUNET_CRYPTO_cpabe_create_key (ai->abe_key,
1967 msg_extra_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
1971 GNUNET_CRYPTO_cpabe_delete_key (key);
1972 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1973 "Found attribute: %s\n", label);
1974 env = GNUNET_MQ_msg_extra (arm,
1976 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1977 arm->id = htonl (ai->request_id);
1978 arm->attr_len = htons (msg_extra_len);
1979 GNUNET_CRYPTO_ecdsa_key_get_public (zone,
1981 data_tmp = (char *) &arm[1];
1982 GNUNET_memcpy (data_tmp,
1985 GNUNET_MQ_send (ai->client->mq, env);
1986 GNUNET_free (attr_ser);
1991 iterate_after_abe_bootstrap (void *cls,
1992 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1994 struct AttributeIterator *ai = cls;
1995 ai->abe_key = abe_key;
1996 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
2002 &attr_iter_finished,
2008 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_START message
2010 * @param cls the client sending the message
2011 * @param zis_msg message from the client
2014 handle_iteration_start (void *cls,
2015 const struct AttributeIterationStartMessage *ais_msg)
2017 struct IdpClient *idp = cls;
2018 struct AttributeIterator *ai;
2020 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2021 "Received ATTRIBUTE_ITERATION_START message\n");
2022 ai = GNUNET_new (struct AttributeIterator);
2023 ai->request_id = ntohl (ais_msg->id);
2025 ai->identity = ais_msg->identity;
2027 GNUNET_CONTAINER_DLL_insert (idp->op_head,
2030 bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
2031 GNUNET_SERVICE_client_continue (idp->client);
2036 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_STOP message
2038 * @param cls the client sending the message
2039 * @param ais_msg message from the client
2042 handle_iteration_stop (void *cls,
2043 const struct AttributeIterationStopMessage *ais_msg)
2045 struct IdpClient *idp = cls;
2046 struct AttributeIterator *ai;
2049 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2050 "Received `%s' message\n",
2051 "ATTRIBUTE_ITERATION_STOP");
2052 rid = ntohl (ais_msg->id);
2053 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2054 if (ai->request_id == rid)
2059 GNUNET_SERVICE_client_drop (idp->client);
2062 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2066 GNUNET_SERVICE_client_continue (idp->client);
2071 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT message
2073 * @param cls the client sending the message
2074 * @param message message from the client
2077 handle_iteration_next (void *cls,
2078 const struct AttributeIterationNextMessage *ais_msg)
2080 struct IdpClient *idp = cls;
2081 struct AttributeIterator *ai;
2084 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2085 "Received ATTRIBUTE_ITERATION_NEXT message\n");
2086 rid = ntohl (ais_msg->id);
2087 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2088 if (ai->request_id == rid)
2093 GNUNET_SERVICE_client_drop (idp->client);
2096 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2097 GNUNET_SERVICE_client_continue (idp->client);
2101 * Ticket iteration processor result
2103 enum ZoneIterationResult
2112 * Continue to iterate with next iteration_next call
2114 IT_SUCCESS_MORE_AVAILABLE = 1,
2117 * Iteration complete
2119 IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
2124 * Context for ticket iteration
2126 struct TicketIterationProcResult
2129 * The ticket iteration handle
2131 struct TicketIteration *ti;
2134 * Iteration result: iteration done?
2135 * #IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but
2136 * we got one for now and have sent it to the client
2137 * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
2138 * #IT_START: if we are still trying to find a result.
2140 int res_iteration_finished;
2145 cleanup_ticket_iter_handle (struct TicketIteration *ti)
2151 * Process ticket from database
2153 * @param cls struct TicketIterationProcResult
2154 * @param ticket the ticket
2155 * @param attrs the attributes
2158 ticket_iterate_proc (void *cls,
2159 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
2160 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
2162 struct TicketIterationProcResult *proc = cls;
2166 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2167 "Iteration done\n");
2168 proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2171 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
2172 send_ticket_result (proc->ti->client,
2180 * Perform ticket iteration step
2182 * @param ti ticket iterator to process
2185 run_ticket_iteration_round (struct TicketIteration *ti)
2187 struct TicketIterationProcResult proc;
2188 struct GNUNET_MQ_Envelope *env;
2189 struct TicketResultMessage *trm;
2192 memset (&proc, 0, sizeof (proc));
2194 proc.res_iteration_finished = IT_START;
2195 while (IT_START == proc.res_iteration_finished)
2197 if (GNUNET_SYSERR ==
2198 (ret = TKT_database->iterate_tickets (TKT_database->cls,
2202 &ticket_iterate_proc,
2208 if (GNUNET_NO == ret)
2209 proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2212 if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
2214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2215 "More results available\n");
2216 return; /* more later */
2218 /* send empty response to indicate end of list */
2219 env = GNUNET_MQ_msg (trm,
2220 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
2221 trm->id = htonl (ti->r_id);
2222 GNUNET_MQ_send (ti->client->mq,
2224 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2225 ti->client->ticket_iter_tail,
2227 cleanup_ticket_iter_handle (ti);
2231 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START message
2233 * @param cls the client sending the message
2234 * @param tis_msg message from the client
2237 handle_ticket_iteration_start (void *cls,
2238 const struct TicketIterationStartMessage *tis_msg)
2240 struct IdpClient *client = cls;
2241 struct TicketIteration *ti;
2243 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2244 "Received TICKET_ITERATION_START message\n");
2245 ti = GNUNET_new (struct TicketIteration);
2246 ti->r_id = ntohl (tis_msg->id);
2248 ti->client = client;
2249 ti->identity = tis_msg->identity;
2250 ti->is_audience = ntohl (tis_msg->is_audience);
2252 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2253 client->ticket_iter_tail,
2255 run_ticket_iteration_round (ti);
2256 GNUNET_SERVICE_client_continue (client->client);
2261 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP message
2263 * @param cls the client sending the message
2264 * @param tis_msg message from the client
2267 handle_ticket_iteration_stop (void *cls,
2268 const struct TicketIterationStopMessage *tis_msg)
2270 struct IdpClient *client = cls;
2271 struct TicketIteration *ti;
2274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2275 "Received `%s' message\n",
2276 "TICKET_ITERATION_STOP");
2277 rid = ntohl (tis_msg->id);
2278 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2279 if (ti->r_id == rid)
2284 GNUNET_SERVICE_client_drop (client->client);
2287 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2288 client->ticket_iter_tail,
2290 cleanup_ticket_iter_handle (ti);
2291 GNUNET_SERVICE_client_continue (client->client);
2296 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT message
2298 * @param cls the client sending the message
2299 * @param message message from the client
2302 handle_ticket_iteration_next (void *cls,
2303 const struct TicketIterationNextMessage *tis_msg)
2305 struct IdpClient *client = cls;
2306 struct TicketIteration *ti;
2309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2310 "Received TICKET_ITERATION_NEXT message\n");
2311 rid = ntohl (tis_msg->id);
2312 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2313 if (ti->r_id == rid)
2318 GNUNET_SERVICE_client_drop (client->client);
2321 run_ticket_iteration_round (ti);
2322 GNUNET_SERVICE_client_continue (client->client);
2329 * Main function that will be run
2331 * @param cls closure
2332 * @param args remaining command-line arguments
2333 * @param cfgfile name of the configuration file used (for saving, can be NULL)
2334 * @param c configuration
2338 const struct GNUNET_CONFIGURATION_Handle *c,
2339 struct GNUNET_SERVICE_Handle *server)
2344 stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
2346 //Connect to identity and namestore services
2347 ns_handle = GNUNET_NAMESTORE_connect (cfg);
2348 if (NULL == ns_handle)
2350 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
2353 gns_handle = GNUNET_GNS_connect (cfg);
2354 if (NULL == gns_handle)
2356 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
2358 credential_handle = GNUNET_CREDENTIAL_connect (cfg);
2359 if (NULL == credential_handle)
2361 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
2363 identity_handle = GNUNET_IDENTITY_connect (cfg,
2367 /* Loading DB plugin */
2369 GNUNET_CONFIGURATION_get_value_string (cfg,
2370 "identity-provider",
2373 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2374 "No database backend configured\n");
2375 GNUNET_asprintf (&db_lib_name,
2376 "libgnunet_plugin_identity_provider_%s",
2378 TKT_database = GNUNET_PLUGIN_load (db_lib_name,
2380 GNUNET_free (database);
2381 if (NULL == TKT_database)
2383 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2384 "Could not load database backend `%s'\n",
2386 GNUNET_SCHEDULER_shutdown ();
2391 GNUNET_CONFIGURATION_get_value_time (cfg,
2392 "identity-provider",
2393 "TOKEN_EXPIRATION_INTERVAL",
2394 &token_expiration_interval))
2396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2397 "Time window for zone iteration: %s\n",
2398 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
2401 token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
2404 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2408 * Called whenever a client is disconnected.
2410 * @param cls closure
2411 * @param client identification of the client
2412 * @param app_ctx @a client
2415 client_disconnect_cb (void *cls,
2416 struct GNUNET_SERVICE_Client *client,
2419 struct IdpClient *idp = app_ctx;
2420 struct AttributeIterator *ai;
2421 struct TicketIteration *ti;
2422 struct TicketRevocationHandle *rh;
2424 //TODO other operations
2426 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2427 "Client %p disconnected\n",
2430 while (NULL != (ai = idp->op_head))
2432 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2437 while (NULL != (rh = idp->revocation_list_head))
2439 GNUNET_CONTAINER_DLL_remove (idp->revocation_list_head,
2440 idp->revocation_list_tail,
2442 cleanup_revoke_ticket_handle (rh);
2444 while (NULL != (ti = idp->ticket_iter_head))
2446 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
2447 idp->ticket_iter_tail,
2449 cleanup_ticket_iter_handle (ti);
2456 * Add a client to our list of active clients.
2459 * @param client client to add
2460 * @param mq message queue for @a client
2461 * @return internal namestore client structure for this client
2464 client_connect_cb (void *cls,
2465 struct GNUNET_SERVICE_Client *client,
2466 struct GNUNET_MQ_Handle *mq)
2468 struct IdpClient *idp;
2469 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2470 "Client %p connected\n",
2472 idp = GNUNET_new (struct IdpClient);
2473 idp->client = client;
2481 * Define "main" method using service macro.
2484 ("identity-provider",
2485 GNUNET_SERVICE_OPTION_NONE,
2488 &client_disconnect_cb,
2490 GNUNET_MQ_hd_var_size (attribute_store_message,
2491 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
2492 struct AttributeStoreMessage,
2494 GNUNET_MQ_hd_fixed_size (iteration_start,
2495 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
2496 struct AttributeIterationStartMessage,
2498 GNUNET_MQ_hd_fixed_size (iteration_next,
2499 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
2500 struct AttributeIterationNextMessage,
2502 GNUNET_MQ_hd_fixed_size (iteration_stop,
2503 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
2504 struct AttributeIterationStopMessage,
2506 GNUNET_MQ_hd_var_size (issue_ticket_message,
2507 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET,
2508 struct IssueTicketMessage,
2510 GNUNET_MQ_hd_var_size (consume_ticket_message,
2511 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
2512 struct ConsumeTicketMessage,
2514 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
2515 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
2516 struct TicketIterationStartMessage,
2518 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2519 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
2520 struct TicketIterationNextMessage,
2522 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2523 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
2524 struct TicketIterationStopMessage,
2526 GNUNET_MQ_hd_var_size (revoke_ticket_message,
2527 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET,
2528 struct RevokeTicketMessage,
2530 GNUNET_MQ_handler_end());
2531 /* end of gnunet-service-identity-provider.c */