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 reissue
478 struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
481 * Attributes to revoke
483 struct GNUNET_IDENTITY_PROVIDER_AttributeList *rvk_attrs;
488 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
493 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
498 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
503 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
508 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
524 * Ticket issue request handle
526 struct TicketIssueHandle
532 struct IdpClient *client;
535 * Attributes to issue
537 struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
542 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
547 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
552 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
562 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
570 struct EgoEntry *next;
575 struct EgoEntry *prev;
580 struct GNUNET_IDENTITY_Ego *ego;
583 * Attribute map. Contains the attributes as json_t
585 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
595 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
599 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
602 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
604 GNUNET_free (db_lib_name);
606 if (NULL != timeout_task)
607 GNUNET_SCHEDULER_cancel (timeout_task);
608 if (NULL != update_task)
609 GNUNET_SCHEDULER_cancel (update_task);
610 if (NULL != identity_handle)
611 GNUNET_IDENTITY_disconnect (identity_handle);
612 if (NULL != gns_handle)
613 GNUNET_GNS_disconnect (gns_handle);
614 if (NULL != credential_handle)
615 GNUNET_CREDENTIAL_disconnect (credential_handle);
617 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
619 GNUNET_NAMESTORE_cancel (ns_qe);
620 if (NULL != ns_handle)
621 GNUNET_NAMESTORE_disconnect (ns_handle);
633 * @param tc task context
636 do_shutdown (void *cls)
638 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
639 "Shutting down...\n");
644 * Finished storing newly bootstrapped ABE key
647 bootstrap_store_cont (void *cls,
651 struct AbeBootstrapHandle *abh = cls;
652 if (GNUNET_SYSERR == success)
654 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
655 "Failed to bootstrap ABE master %s\n",
657 abh->proc (abh->proc_cls, NULL);
658 GNUNET_free (abh->abe_key);
662 abh->proc (abh->proc_cls, abh->abe_key);
667 * Generates and stores a new ABE key
670 bootstrap_store_task (void *cls)
672 struct AbeBootstrapHandle *abh = cls;
673 struct GNUNET_GNSRECORD_Data rd[1];
675 rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (abh->abe_key,
676 (void**)&rd[0].data);
677 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
678 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
679 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
680 abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
685 &bootstrap_store_cont,
687 GNUNET_free ((void*)rd[0].data);
691 * Error checking for ABE master
694 bootstrap_abe_error (void *cls)
696 struct AbeBootstrapHandle *abh = cls;
698 abh->proc (abh->proc_cls, NULL);
704 * Handle ABE lookup in namestore
707 bootstrap_abe_result (void *cls,
708 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
710 unsigned int rd_count,
711 const struct GNUNET_GNSRECORD_Data *rd)
713 struct AbeBootstrapHandle *abh = cls;
714 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
717 for (i=0;i<rd_count;i++) {
718 if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
720 abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key ((void**)rd[i].data,
722 abh->proc (abh->proc_cls, abe_key);
727 //No ABE master found, bootstrapping...
728 abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
729 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
733 * Bootstrap ABE master if it does not yet exists.
734 * Will call the AbeBootstrapResult processor when done.
735 * will always recreate the ABE key of GNUNET_YES == recreate
738 bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
739 AbeBootstrapResult proc,
743 struct AbeBootstrapHandle *abh;
745 abh = GNUNET_new (struct AbeBootstrapHandle);
748 abh->identity = *identity;
749 if (GNUNET_YES == recreate)
751 abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
752 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
754 abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
757 &bootstrap_abe_error,
759 &bootstrap_abe_result,
767 create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
768 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
769 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
771 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
773 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
775 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
776 static const char ctx_key[] = "gnuid-aes-ctx-key";
777 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
778 new_key_hash, sizeof (struct GNUNET_HashCode),
779 ctx_key, strlen (ctx_key),
781 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
782 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
783 new_key_hash, sizeof (struct GNUNET_HashCode),
784 ctx_iv, strlen (ctx_iv),
790 cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
792 if (NULL != handle->attrs)
793 attribute_list_destroy (handle->attrs);
794 if (NULL != handle->ns_qe)
795 GNUNET_NAMESTORE_cancel (handle->ns_qe);
796 GNUNET_free (handle);
801 send_ticket_result (struct IdpClient *client,
803 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
804 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
806 struct TicketResultMessage *irm;
807 struct GNUNET_MQ_Envelope *env;
808 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
810 /* store ticket in DB */
811 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
815 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
816 "Unable to store ticket after issue\n");
820 env = GNUNET_MQ_msg_extra (irm,
821 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
822 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
823 ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
824 *ticket_buf = *ticket;
825 irm->id = htonl (r_id);
826 GNUNET_MQ_send (client->mq,
831 store_ticket_issue_cont (void *cls,
835 struct TicketIssueHandle *handle = cls;
837 handle->ns_qe = NULL;
838 if (GNUNET_SYSERR == success)
840 cleanup_ticket_issue_handle (handle);
841 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
843 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
846 send_ticket_result (handle->client,
850 cleanup_ticket_issue_handle (handle);
856 serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
857 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs,
858 const struct GNUNET_CRYPTO_AbeKey *rp_key,
859 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
862 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
863 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
865 char *serialized_key;
871 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
872 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
873 struct GNUNET_HashCode new_key_hash;
876 size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key,
877 (void**)&serialized_key);
879 for (le = attrs->list_head; NULL != le; le = le->next) {
880 attrs_str_len += strlen (le->attribute->name) + 1;
882 buf = GNUNET_malloc (attrs_str_len + size);
884 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
885 "Writing attributes\n");
886 for (le = attrs->list_head; NULL != le; le = le->next) {
887 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
888 "%s\n", le->attribute->name);
891 GNUNET_memcpy (write_ptr,
893 strlen (le->attribute->name));
894 write_ptr[strlen (le->attribute->name)] = ',';
895 write_ptr += strlen (le->attribute->name) + 1;
898 write_ptr[0] = '\0'; //replace last , with a 0-terminator
900 GNUNET_memcpy (write_ptr,
903 // ECDH keypair E = eG
904 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
905 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
907 enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
908 // Derived key K = H(eB)
909 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
912 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
913 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
914 size + attrs_str_len,
917 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
919 GNUNET_memcpy (*result,
921 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
922 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
925 GNUNET_free (enc_keyinfo);
927 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
933 issue_ticket_after_abe_bootstrap (void *cls,
934 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
936 struct TicketIssueHandle *ih = cls;
937 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
938 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
939 struct GNUNET_GNSRECORD_Data code_record[1];
940 struct GNUNET_CRYPTO_AbeKey *rp_key;
941 char *code_record_data;
946 size_t code_record_len;
948 //Create new ABE key for RP
950 for (le = ih->attrs->list_head; NULL != le; le = le->next)
952 attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
954 for (le = ih->attrs->list_head; NULL != le; le = le->next) {
955 attrs[i] = (char*) le->attribute->name;
959 rp_key = GNUNET_CRYPTO_cpabe_create_key (abe_key,
962 //TODO review this wireformat
963 code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
968 code_record[0].data = code_record_data;
969 code_record[0].data_size = code_record_len;
970 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
971 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
972 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
974 label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
977 ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
982 &store_ticket_issue_cont,
984 GNUNET_free (ecdhe_privkey);
987 GNUNET_free (code_record_data);
988 GNUNET_CRYPTO_cpabe_delete_master_key (abe_key);
989 GNUNET_CRYPTO_cpabe_delete_key (rp_key);
994 * Checks a ticket issue message
996 * @param cls client sending the message
997 * @param im message of type `struct TicketIssueMessage`
998 * @return #GNUNET_OK if @a im is well-formed
1001 check_issue_ticket_message(void *cls,
1002 const struct IssueTicketMessage *im)
1006 size = ntohs (im->header.size);
1007 if (size <= sizeof (struct IssueTicketMessage))
1010 return GNUNET_SYSERR;
1018 * Handler for ticket issue message
1021 * @param client who sent the message
1022 * @param message the message
1025 handle_issue_ticket_message (void *cls,
1026 const struct IssueTicketMessage *im)
1028 struct TicketIssueHandle *ih;
1029 struct IdpClient *idp = cls;
1032 ih = GNUNET_new (struct TicketIssueHandle);
1033 attrs_len = ntohs (im->attr_len);
1034 ih->attrs = attribute_list_deserialize ((char*)&im[1], attrs_len);
1035 ih->r_id = ntohl (im->id);
1037 ih->identity = im->identity;
1038 GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
1039 &ih->ticket.identity);
1040 ih->ticket.audience = im->rp;
1042 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1044 bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
1045 GNUNET_SERVICE_client_continue (idp->client);
1049 /**********************************************************
1051 **********************************************************/
1054 * Cleanup revoke handle
1057 cleanup_revoke_ticket_handle (struct TicketRevocationHandle *handle)
1059 if (NULL != handle->attrs)
1060 attribute_list_destroy (handle->attrs);
1061 if (NULL != handle->rvk_attrs)
1062 attribute_list_destroy (handle->rvk_attrs);
1063 if (NULL != handle->abe_key)
1064 GNUNET_CRYPTO_cpabe_delete_master_key (handle->abe_key);
1065 if (NULL != handle->ns_qe)
1066 GNUNET_NAMESTORE_cancel (handle->ns_qe);
1067 if (NULL != handle->ns_it)
1068 GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
1069 GNUNET_free (handle);
1074 * Send revocation result
1077 send_revocation_finished (struct TicketRevocationHandle *rh,
1080 struct GNUNET_MQ_Envelope *env;
1081 struct RevokeTicketResultMessage *trm;
1083 env = GNUNET_MQ_msg (trm,
1084 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT);
1085 trm->id = htonl (rh->r_id);
1086 trm->success = htonl (success);
1087 GNUNET_MQ_send (rh->client->mq,
1089 GNUNET_CONTAINER_DLL_remove (rh->client->revocation_list_head,
1090 rh->client->revocation_list_tail,
1096 * Process ticket from database
1098 * @param cls struct TicketIterationProcResult
1099 * @param ticket the ticket
1100 * @param attrs the attributes
1103 ticket_reissue_proc (void *cls,
1104 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1105 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs);
1109 reissue_ticket_cont (void *cls,
1113 struct TicketRevocationHandle *rh = cls;
1117 if (GNUNET_SYSERR == success)
1119 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1121 send_revocation_finished (rh, GNUNET_SYSERR);
1122 cleanup_revoke_ticket_handle (rh);
1125 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Continue DB iteration\n");
1127 GNUNET_assert (GNUNET_SYSERR != (ret =
1128 TKT_database->iterate_tickets (TKT_database->cls,
1129 &rh->ticket.identity,
1132 &ticket_reissue_proc,
1134 if (GNUNET_NO == ret)
1136 send_revocation_finished (rh, GNUNET_OK);
1137 cleanup_revoke_ticket_handle (rh);
1144 * Process ticket from database
1146 * @param cls struct TicketIterationProcResult
1147 * @param ticket the ticket
1148 * @param attrs the attributes
1151 ticket_reissue_proc (void *cls,
1152 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1153 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
1155 struct TicketRevocationHandle *rh = cls;
1156 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1157 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
1158 struct GNUNET_GNSRECORD_Data code_record[1];
1159 struct GNUNET_CRYPTO_AbeKey *rp_key;
1160 char *code_record_data;
1165 size_t code_record_len;
1170 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1171 "Iteration done\n");
1172 send_revocation_finished (rh, GNUNET_OK);
1173 cleanup_revoke_ticket_handle (rh);
1176 //Create new ABE key for RP
1179 /* If this is the RP we want to revoke attributes of, the do so */
1181 for (le = attrs->list_head; NULL != le; le = le->next)
1183 attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1185 for (le = attrs->list_head; NULL != le; le = le->next) {
1186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1187 "Recreating key with %s\n", (char*) le->attribute->name);
1188 attr_arr[i] = (char*) le->attribute->name;
1192 rp_key = GNUNET_CRYPTO_cpabe_create_key (rh->abe_key,
1195 //TODO review this wireformat
1196 code_record_len = serialize_abe_keyinfo2 (&rh->ticket,
1201 code_record[0].data = code_record_data;
1202 code_record[0].data_size = code_record_len;
1203 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1204 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1205 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1207 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
1210 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1215 &reissue_ticket_cont,
1217 GNUNET_free (ecdhe_privkey);
1218 GNUNET_free (label);
1219 GNUNET_free (attr_arr);
1220 GNUNET_free (code_record_data);
1221 GNUNET_CRYPTO_cpabe_delete_key (rp_key);
1225 /* Prototype for below function */
1227 attr_reenc_cont (void *cls,
1232 revocation_reissue_tickets (struct TicketRevocationHandle *rh)
1235 /* Done, issue new keys */
1236 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1237 "Revocation Phase IV: Reissuing Tickets\n");
1238 if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
1239 &rh->ticket.identity,
1242 &ticket_reissue_proc,
1247 if (GNUNET_NO == ret)
1249 send_revocation_finished (rh, GNUNET_OK);
1250 cleanup_revoke_ticket_handle (rh);
1256 * Revoke next attribte by reencryption with
1260 reenc_next_attribute (struct TicketRevocationHandle *rh)
1262 struct GNUNET_GNSRECORD_Data rd[1];
1267 if (NULL == rh->attrs->list_head)
1269 revocation_reissue_tickets (rh);
1273 buf_size = attribute_serialize_get_size (rh->attrs->list_head->attribute);
1274 buf = GNUNET_malloc (buf_size);
1276 attribute_serialize (rh->attrs->list_head->attribute,
1280 * Encrypt the attribute value and store in namestore
1282 rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1284 rh->attrs->list_head->attribute->name, //Policy
1288 rd[0].data = enc_buf;
1289 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1290 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1291 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1292 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1294 rh->attrs->list_head->attribute->name,
1299 GNUNET_free (enc_buf);
1304 * Namestore callback after revoked attribute
1308 attr_reenc_cont (void *cls,
1312 struct TicketRevocationHandle *rh = cls;
1313 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1315 if (GNUNET_SYSERR == success)
1317 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1318 "Failed to reencrypt attribute %s\n",
1320 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1323 if (NULL == rh->attrs->list_head)
1325 revocation_reissue_tickets (rh);
1328 le = rh->attrs->list_head;
1329 GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1330 rh->attrs->list_tail,
1332 GNUNET_free (le->attribute);
1336 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1337 "Re-encrypting next attribute\n");
1338 reenc_next_attribute (rh);
1343 * Start reencryption with newly generated ABE master
1346 reenc_after_abe_bootstrap (void *cls,
1347 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1349 struct TicketRevocationHandle *rh = cls;
1350 GNUNET_free (rh->abe_key);
1351 GNUNET_assert (NULL != abe_key);
1352 rh->abe_key = abe_key;
1354 if (NULL == rh->attrs->list_head)
1356 /* No attributes to reencrypt */
1357 send_revocation_finished (rh, GNUNET_OK);
1358 cleanup_revoke_ticket_handle (rh);
1361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1362 "Revocation Phase III: Re-encrypting attributes\n");
1363 reenc_next_attribute (rh);
1369 * Collecting attributes failed... abort.
1372 revoke_collect_iter_error (void *cls)
1374 struct TicketRevocationHandle *rh = cls;
1376 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1377 "Failed to iterate over attributes\n");
1379 send_revocation_finished (rh, GNUNET_SYSERR);
1380 cleanup_revoke_ticket_handle (rh);
1384 * Done decrypting existing attributes.
1387 revoke_collect_iter_finished (void *cls)
1389 struct TicketRevocationHandle *rh = cls;
1391 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1392 "Revocation Phase II: Invalidating old ABE Master\n");
1393 /* Bootstrap new abe key */
1394 bootstrap_abe (&rh->identity, &reenc_after_abe_bootstrap, rh, GNUNET_YES);
1398 * Decrypt existing attribute and store it
1399 * We will revoke it by reencrypting it with a new ABE master key.
1402 revoke_collect_iter_cb (void *cls,
1403 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1405 unsigned int rd_count,
1406 const struct GNUNET_GNSRECORD_Data *rd)
1408 struct TicketRevocationHandle *rh = cls;
1409 struct GNUNET_CRYPTO_AbeKey *key;
1410 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1417 GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it);
1421 if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
1422 GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it);
1425 attrs[0] = (char*)label;
1427 key = GNUNET_CRYPTO_cpabe_create_key (rh->abe_key,
1429 attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
1433 GNUNET_CRYPTO_cpabe_delete_key (key);
1434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1435 "Attribute to reencrypt: %s\n", label);
1436 le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
1437 le->attribute = attribute_deserialize (attr_ser, attr_len);
1438 GNUNET_free (attr_ser);
1439 GNUNET_CONTAINER_DLL_insert_tail (rh->attrs->list_head,
1440 rh->attrs->list_tail,
1442 GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it);
1446 * Start attribute collection for revocation
1449 collect_after_abe_bootstrap (void *cls,
1450 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1452 struct TicketRevocationHandle *rh = cls;
1454 rh->abe_key = abe_key;
1455 GNUNET_assert (NULL != abe_key);
1456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1457 "Revocation Phase I: Collecting attributes\n");
1458 /* Reencrypt all attributes with new key */
1459 rh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1461 &revoke_collect_iter_error,
1463 &revoke_collect_iter_cb,
1465 &revoke_collect_iter_finished,
1472 * Checks a ticket revocation message
1474 * @param cls client sending the message
1475 * @param im message of type `struct RevokeTicketMessage`
1476 * @return #GNUNET_OK if @a im is well-formed
1479 check_revoke_ticket_message(void *cls,
1480 const struct RevokeTicketMessage *im)
1484 size = ntohs (im->header.size);
1485 if (size <= sizeof (struct RevokeTicketMessage))
1488 return GNUNET_SYSERR;
1496 * Handler for ticket revocation message
1499 * @param client who sent the message
1500 * @param message the message
1503 handle_revoke_ticket_message (void *cls,
1504 const struct RevokeTicketMessage *rm)
1506 struct TicketRevocationHandle *rh;
1507 struct IdpClient *idp = cls;
1508 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
1511 rh = GNUNET_new (struct TicketRevocationHandle);
1512 attrs_len = ntohs (rm->attrs_len);
1513 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1];
1515 rh->rvk_attrs = attribute_list_deserialize ((char*)&ticket[1], attrs_len);
1516 rh->attrs = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
1517 rh->ticket = *ticket;
1518 rh->r_id = ntohl (rm->id);
1520 rh->identity = rm->identity;
1521 GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
1522 &rh->ticket.identity);
1523 GNUNET_CONTAINER_DLL_insert (idp->revocation_list_head,
1524 idp->revocation_list_tail,
1526 bootstrap_abe (&rh->identity, &collect_after_abe_bootstrap, rh, GNUNET_NO);
1527 GNUNET_SERVICE_client_continue (idp->client);
1533 cleanup_as_handle (struct AttributeStoreHandle *handle)
1535 if (NULL != handle->attribute)
1536 GNUNET_free (handle->attribute);
1537 if (NULL != handle->abe_key)
1538 GNUNET_CRYPTO_cpabe_delete_master_key (handle->abe_key);
1539 GNUNET_free (handle);
1543 * Checks a ticket consume message
1545 * @param cls client sending the message
1546 * @param im message of type `struct ConsumeTicketMessage`
1547 * @return #GNUNET_OK if @a im is well-formed
1550 check_consume_ticket_message(void *cls,
1551 const struct ConsumeTicketMessage *cm)
1555 size = ntohs (cm->header.size);
1556 if (size <= sizeof (struct ConsumeTicketMessage))
1559 return GNUNET_SYSERR;
1565 process_parallel_lookup2 (void *cls, uint32_t rd_count,
1566 const struct GNUNET_GNSRECORD_Data *rd)
1568 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1569 "Parallel lookup finished (count=%u)\n", rd_count);
1570 struct ParallelLookup *parallel_lookup = cls;
1571 struct ConsumeTicketHandle *handle = parallel_lookup->handle;
1572 struct ConsumeTicketResultMessage *crm;
1573 struct GNUNET_MQ_Envelope *env;
1574 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *attr_le;
1580 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1581 handle->parallel_lookups_tail,
1583 GNUNET_free (parallel_lookup->label);
1584 GNUNET_free (parallel_lookup);
1586 GNUNET_break(0);//TODO
1587 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1589 attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
1593 attr_le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
1594 attr_le->attribute = attribute_deserialize (data,
1596 GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
1597 handle->attrs->list_tail,
1601 if (NULL != handle->parallel_lookups_head)
1602 return; //Wait for more
1603 /* Else we are done */
1605 /* Store ticket in DB */
1606 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1610 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1611 "Unable to store ticket after consume\n");
1615 GNUNET_SCHEDULER_cancel (handle->kill_task);
1616 attrs_len = attribute_list_serialize_get_size (handle->attrs);
1617 env = GNUNET_MQ_msg_extra (crm,
1619 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
1620 crm->id = htonl (handle->r_id);
1621 crm->attrs_len = htons (attrs_len);
1622 crm->identity = handle->ticket.identity;
1623 data_tmp = (char *) &crm[1];
1624 attribute_list_serialize (handle->attrs,
1626 GNUNET_MQ_send (handle->client->mq, env);
1630 abort_parallel_lookups2 (void *cls)
1632 struct ConsumeTicketHandle *handle = cls;
1633 struct ParallelLookup *lu;
1634 struct ParallelLookup *tmp;
1635 struct AttributeResultMessage *arm;
1636 struct GNUNET_MQ_Envelope *env;
1638 for (lu = handle->parallel_lookups_head;
1640 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1641 GNUNET_free (lu->label);
1643 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1644 handle->parallel_lookups_tail,
1649 env = GNUNET_MQ_msg (arm,
1650 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1651 arm->id = htonl (handle->r_id);
1652 arm->attr_len = htons (0);
1653 GNUNET_MQ_send (handle->client->mq, env);
1658 cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
1660 if (NULL != handle->key)
1661 GNUNET_CRYPTO_cpabe_delete_key (handle->key);
1662 GNUNET_free (handle);
1667 process_consume_abe_key (void *cls, uint32_t rd_count,
1668 const struct GNUNET_GNSRECORD_Data *rd)
1670 struct ConsumeTicketHandle *handle = cls;
1671 struct GNUNET_HashCode new_key_hash;
1672 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1673 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1674 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1675 struct ParallelLookup *parallel_lookup;
1681 handle->lookup_request = NULL;
1684 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1685 "Number of keys %d != 1.",
1687 cleanup_consume_ticket_handle (handle);
1688 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1693 ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1695 buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1697 //Calculate symmetric key from ecdh parameters
1698 GNUNET_assert (GNUNET_OK ==
1699 GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
1702 create_sym_key_from_ecdh (&new_key_hash,
1705 size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1706 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1711 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1712 "Decrypted bytes: %zd Expected bytes: %zd\n",
1713 size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1715 scopes = GNUNET_strdup (buf);
1716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1717 "Scopes %s\n", scopes);
1718 handle->key = GNUNET_CRYPTO_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1719 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1720 - strlen (scopes) - 1);
1722 for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1724 GNUNET_asprintf (&lookup_query,
1727 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1728 "Looking up %s\n", lookup_query);
1729 parallel_lookup = GNUNET_new (struct ParallelLookup);
1730 parallel_lookup->handle = handle;
1731 parallel_lookup->label = GNUNET_strdup (scope);
1732 parallel_lookup->lookup_request
1733 = GNUNET_GNS_lookup (gns_handle,
1735 &handle->ticket.identity,
1736 GNUNET_GNSRECORD_TYPE_ID_ATTR,
1737 GNUNET_GNS_LO_LOCAL_MASTER,
1738 &process_parallel_lookup2,
1740 GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1741 handle->parallel_lookups_tail,
1743 GNUNET_free (lookup_query);
1745 handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1746 &abort_parallel_lookups2,
1753 * Handler for ticket issue message
1756 * @param client who sent the message
1757 * @param message the message
1760 handle_consume_ticket_message (void *cls,
1761 const struct ConsumeTicketMessage *cm)
1763 struct ConsumeTicketHandle *ch;
1764 struct IdpClient *idp = cls;
1768 ch = GNUNET_new (struct ConsumeTicketHandle);
1769 ch->r_id = ntohl (cm->id);
1771 ch->identity = cm->identity;
1772 ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
1773 GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
1775 ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
1776 rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
1778 GNUNET_asprintf (&lookup_query,
1781 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1782 "Looking for ABE key under %s\n", lookup_query);
1785 = GNUNET_GNS_lookup (gns_handle,
1787 &ch->ticket.identity,
1788 GNUNET_GNSRECORD_TYPE_ABE_KEY,
1789 GNUNET_GNS_LO_LOCAL_MASTER,
1790 &process_consume_abe_key,
1792 GNUNET_free (rnd_label);
1793 GNUNET_free (lookup_query);
1794 GNUNET_SERVICE_client_continue (idp->client);
1798 attr_store_cont (void *cls,
1802 struct AttributeStoreHandle *as_handle = cls;
1803 struct GNUNET_MQ_Envelope *env;
1804 struct AttributeStoreResultMessage *acr_msg;
1806 if (GNUNET_SYSERR == success)
1808 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1809 "Failed to store attribute %s\n",
1811 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1815 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1816 "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1817 env = GNUNET_MQ_msg (acr_msg,
1818 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
1819 acr_msg->id = htonl (as_handle->r_id);
1820 acr_msg->op_result = htonl (GNUNET_OK);
1821 GNUNET_MQ_send (as_handle->client->mq,
1823 cleanup_as_handle (as_handle);
1827 attr_store_task (void *cls)
1829 struct AttributeStoreHandle *as_handle = cls;
1830 struct GNUNET_GNSRECORD_Data rd[1];
1834 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1835 "Storing attribute\n");
1836 buf_size = attribute_serialize_get_size (as_handle->attribute);
1837 buf = GNUNET_malloc (buf_size);
1839 attribute_serialize (as_handle->attribute,
1843 * Encrypt the attribute value and store in namestore
1845 rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1847 as_handle->attribute->name, //Policy
1849 (void**)&rd[0].data);
1851 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1852 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1853 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1854 as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1855 &as_handle->identity,
1856 as_handle->attribute->name,
1861 GNUNET_free ((void*)rd[0].data);
1867 store_after_abe_bootstrap (void *cls,
1868 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1870 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1871 "Finished ABE bootstrap\n");
1872 struct AttributeStoreHandle *ash = cls;
1873 ash->abe_key = abe_key;
1874 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1878 * Checks a store message
1880 * @param cls client sending the message
1881 * @param sam message of type `struct AttributeStoreMessage`
1882 * @return #GNUNET_OK if @a im is well-formed
1885 check_attribute_store_message(void *cls,
1886 const struct AttributeStoreMessage *sam)
1890 size = ntohs (sam->header.size);
1891 if (size <= sizeof (struct AttributeStoreMessage))
1894 return GNUNET_SYSERR;
1902 * Handler for store message
1905 * @param client who sent the message
1906 * @param message the message
1909 handle_attribute_store_message (void *cls,
1910 const struct AttributeStoreMessage *sam)
1912 struct AttributeStoreHandle *as_handle;
1913 struct IdpClient *idp = cls;
1915 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1916 "Received ATTRIBUTE_STORE message\n");
1918 data_len = ntohs (sam->attr_len);
1920 as_handle = GNUNET_new (struct AttributeStoreHandle);
1921 as_handle->attribute = attribute_deserialize ((char*)&sam[1],
1924 as_handle->r_id = ntohl (sam->id);
1925 as_handle->identity = sam->identity;
1926 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1927 &as_handle->identity_pkey);
1929 GNUNET_SERVICE_client_continue (idp->client);
1930 as_handle->client = idp;
1931 bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
1935 cleanup_iter_handle (struct AttributeIterator *ai)
1937 if (NULL != ai->abe_key)
1938 GNUNET_free (ai->abe_key);
1939 GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
1940 ai->client->op_tail,
1946 attr_iter_error (void *cls)
1948 //struct AttributeIterator *ai = cls;
1950 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1951 "Failed to iterate over attributes\n");
1952 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1956 attr_iter_finished (void *cls)
1958 struct AttributeIterator *ai = cls;
1959 struct GNUNET_MQ_Envelope *env;
1960 struct AttributeResultMessage *arm;
1962 env = GNUNET_MQ_msg (arm,
1963 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1964 arm->id = htonl (ai->request_id);
1965 arm->attr_len = htons (0);
1966 GNUNET_MQ_send (ai->client->mq, env);
1967 cleanup_iter_handle (ai);
1971 attr_iter_cb (void *cls,
1972 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1974 unsigned int rd_count,
1975 const struct GNUNET_GNSRECORD_Data *rd)
1977 struct AttributeIterator *ai = cls;
1978 struct AttributeResultMessage *arm;
1979 struct GNUNET_CRYPTO_AbeKey *key;
1980 struct GNUNET_MQ_Envelope *env;
1981 ssize_t msg_extra_len;
1988 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1992 if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
1993 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1996 attrs[0] = (char*)label;
1998 key = GNUNET_CRYPTO_cpabe_create_key (ai->abe_key,
2000 msg_extra_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
2004 GNUNET_CRYPTO_cpabe_delete_key (key);
2005 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2006 "Found attribute: %s\n", label);
2007 env = GNUNET_MQ_msg_extra (arm,
2009 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
2010 arm->id = htonl (ai->request_id);
2011 arm->attr_len = htons (msg_extra_len);
2012 GNUNET_CRYPTO_ecdsa_key_get_public (zone,
2014 data_tmp = (char *) &arm[1];
2015 GNUNET_memcpy (data_tmp,
2018 GNUNET_MQ_send (ai->client->mq, env);
2019 GNUNET_free (attr_ser);
2024 iterate_after_abe_bootstrap (void *cls,
2025 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
2027 struct AttributeIterator *ai = cls;
2028 ai->abe_key = abe_key;
2029 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
2035 &attr_iter_finished,
2041 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_START message
2043 * @param cls the client sending the message
2044 * @param zis_msg message from the client
2047 handle_iteration_start (void *cls,
2048 const struct AttributeIterationStartMessage *ais_msg)
2050 struct IdpClient *idp = cls;
2051 struct AttributeIterator *ai;
2053 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2054 "Received ATTRIBUTE_ITERATION_START message\n");
2055 ai = GNUNET_new (struct AttributeIterator);
2056 ai->request_id = ntohl (ais_msg->id);
2058 ai->identity = ais_msg->identity;
2060 GNUNET_CONTAINER_DLL_insert (idp->op_head,
2063 bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
2064 GNUNET_SERVICE_client_continue (idp->client);
2069 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_STOP message
2071 * @param cls the client sending the message
2072 * @param ais_msg message from the client
2075 handle_iteration_stop (void *cls,
2076 const struct AttributeIterationStopMessage *ais_msg)
2078 struct IdpClient *idp = cls;
2079 struct AttributeIterator *ai;
2082 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2083 "Received `%s' message\n",
2084 "ATTRIBUTE_ITERATION_STOP");
2085 rid = ntohl (ais_msg->id);
2086 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2087 if (ai->request_id == rid)
2092 GNUNET_SERVICE_client_drop (idp->client);
2095 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2099 GNUNET_SERVICE_client_continue (idp->client);
2104 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT message
2106 * @param cls the client sending the message
2107 * @param message message from the client
2110 handle_iteration_next (void *cls,
2111 const struct AttributeIterationNextMessage *ais_msg)
2113 struct IdpClient *idp = cls;
2114 struct AttributeIterator *ai;
2117 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2118 "Received ATTRIBUTE_ITERATION_NEXT message\n");
2119 rid = ntohl (ais_msg->id);
2120 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2121 if (ai->request_id == rid)
2126 GNUNET_SERVICE_client_drop (idp->client);
2129 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2130 GNUNET_SERVICE_client_continue (idp->client);
2134 * Ticket iteration processor result
2136 enum ZoneIterationResult
2145 * Continue to iterate with next iteration_next call
2147 IT_SUCCESS_MORE_AVAILABLE = 1,
2150 * Iteration complete
2152 IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
2157 * Context for ticket iteration
2159 struct TicketIterationProcResult
2162 * The ticket iteration handle
2164 struct TicketIteration *ti;
2167 * Iteration result: iteration done?
2168 * #IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but
2169 * we got one for now and have sent it to the client
2170 * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
2171 * #IT_START: if we are still trying to find a result.
2173 int res_iteration_finished;
2178 cleanup_ticket_iter_handle (struct TicketIteration *ti)
2184 * Process ticket from database
2186 * @param cls struct TicketIterationProcResult
2187 * @param ticket the ticket
2188 * @param attrs the attributes
2191 ticket_iterate_proc (void *cls,
2192 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
2193 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
2195 struct TicketIterationProcResult *proc = cls;
2199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2200 "Iteration done\n");
2201 proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2204 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
2205 send_ticket_result (proc->ti->client,
2213 * Perform ticket iteration step
2215 * @param ti ticket iterator to process
2218 run_ticket_iteration_round (struct TicketIteration *ti)
2220 struct TicketIterationProcResult proc;
2221 struct GNUNET_MQ_Envelope *env;
2222 struct TicketResultMessage *trm;
2225 memset (&proc, 0, sizeof (proc));
2227 proc.res_iteration_finished = IT_START;
2228 while (IT_START == proc.res_iteration_finished)
2230 if (GNUNET_SYSERR ==
2231 (ret = TKT_database->iterate_tickets (TKT_database->cls,
2235 &ticket_iterate_proc,
2241 if (GNUNET_NO == ret)
2242 proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2245 if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
2247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2248 "More results available\n");
2249 return; /* more later */
2251 /* send empty response to indicate end of list */
2252 env = GNUNET_MQ_msg (trm,
2253 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
2254 trm->id = htonl (ti->r_id);
2255 GNUNET_MQ_send (ti->client->mq,
2257 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2258 ti->client->ticket_iter_tail,
2260 cleanup_ticket_iter_handle (ti);
2264 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START message
2266 * @param cls the client sending the message
2267 * @param tis_msg message from the client
2270 handle_ticket_iteration_start (void *cls,
2271 const struct TicketIterationStartMessage *tis_msg)
2273 struct IdpClient *client = cls;
2274 struct TicketIteration *ti;
2276 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2277 "Received TICKET_ITERATION_START message\n");
2278 ti = GNUNET_new (struct TicketIteration);
2279 ti->r_id = ntohl (tis_msg->id);
2281 ti->client = client;
2282 ti->identity = tis_msg->identity;
2283 ti->is_audience = ntohl (tis_msg->is_audience);
2285 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2286 client->ticket_iter_tail,
2288 run_ticket_iteration_round (ti);
2289 GNUNET_SERVICE_client_continue (client->client);
2294 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP message
2296 * @param cls the client sending the message
2297 * @param tis_msg message from the client
2300 handle_ticket_iteration_stop (void *cls,
2301 const struct TicketIterationStopMessage *tis_msg)
2303 struct IdpClient *client = cls;
2304 struct TicketIteration *ti;
2307 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2308 "Received `%s' message\n",
2309 "TICKET_ITERATION_STOP");
2310 rid = ntohl (tis_msg->id);
2311 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2312 if (ti->r_id == rid)
2317 GNUNET_SERVICE_client_drop (client->client);
2320 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2321 client->ticket_iter_tail,
2323 cleanup_ticket_iter_handle (ti);
2324 GNUNET_SERVICE_client_continue (client->client);
2329 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT message
2331 * @param cls the client sending the message
2332 * @param message message from the client
2335 handle_ticket_iteration_next (void *cls,
2336 const struct TicketIterationNextMessage *tis_msg)
2338 struct IdpClient *client = cls;
2339 struct TicketIteration *ti;
2342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2343 "Received TICKET_ITERATION_NEXT message\n");
2344 rid = ntohl (tis_msg->id);
2345 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2346 if (ti->r_id == rid)
2351 GNUNET_SERVICE_client_drop (client->client);
2354 run_ticket_iteration_round (ti);
2355 GNUNET_SERVICE_client_continue (client->client);
2362 * Main function that will be run
2364 * @param cls closure
2365 * @param args remaining command-line arguments
2366 * @param cfgfile name of the configuration file used (for saving, can be NULL)
2367 * @param c configuration
2371 const struct GNUNET_CONFIGURATION_Handle *c,
2372 struct GNUNET_SERVICE_Handle *server)
2377 stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
2379 //Connect to identity and namestore services
2380 ns_handle = GNUNET_NAMESTORE_connect (cfg);
2381 if (NULL == ns_handle)
2383 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
2386 gns_handle = GNUNET_GNS_connect (cfg);
2387 if (NULL == gns_handle)
2389 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
2391 credential_handle = GNUNET_CREDENTIAL_connect (cfg);
2392 if (NULL == credential_handle)
2394 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
2396 identity_handle = GNUNET_IDENTITY_connect (cfg,
2400 /* Loading DB plugin */
2402 GNUNET_CONFIGURATION_get_value_string (cfg,
2403 "identity-provider",
2406 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2407 "No database backend configured\n");
2408 GNUNET_asprintf (&db_lib_name,
2409 "libgnunet_plugin_identity_provider_%s",
2411 TKT_database = GNUNET_PLUGIN_load (db_lib_name,
2413 GNUNET_free (database);
2414 if (NULL == TKT_database)
2416 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2417 "Could not load database backend `%s'\n",
2419 GNUNET_SCHEDULER_shutdown ();
2424 GNUNET_CONFIGURATION_get_value_time (cfg,
2425 "identity-provider",
2426 "TOKEN_EXPIRATION_INTERVAL",
2427 &token_expiration_interval))
2429 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2430 "Time window for zone iteration: %s\n",
2431 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
2434 token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
2437 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2441 * Called whenever a client is disconnected.
2443 * @param cls closure
2444 * @param client identification of the client
2445 * @param app_ctx @a client
2448 client_disconnect_cb (void *cls,
2449 struct GNUNET_SERVICE_Client *client,
2452 struct IdpClient *idp = app_ctx;
2453 struct AttributeIterator *ai;
2454 struct TicketIteration *ti;
2455 struct TicketRevocationHandle *rh;
2457 //TODO other operations
2459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2460 "Client %p disconnected\n",
2463 while (NULL != (ai = idp->op_head))
2465 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2470 while (NULL != (rh = idp->revocation_list_head))
2472 GNUNET_CONTAINER_DLL_remove (idp->revocation_list_head,
2473 idp->revocation_list_tail,
2475 cleanup_revoke_ticket_handle (rh);
2477 while (NULL != (ti = idp->ticket_iter_head))
2479 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
2480 idp->ticket_iter_tail,
2482 cleanup_ticket_iter_handle (ti);
2489 * Add a client to our list of active clients.
2492 * @param client client to add
2493 * @param mq message queue for @a client
2494 * @return internal namestore client structure for this client
2497 client_connect_cb (void *cls,
2498 struct GNUNET_SERVICE_Client *client,
2499 struct GNUNET_MQ_Handle *mq)
2501 struct IdpClient *idp;
2502 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2503 "Client %p connected\n",
2505 idp = GNUNET_new (struct IdpClient);
2506 idp->client = client;
2514 * Define "main" method using service macro.
2517 ("identity-provider",
2518 GNUNET_SERVICE_OPTION_NONE,
2521 &client_disconnect_cb,
2523 GNUNET_MQ_hd_var_size (attribute_store_message,
2524 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
2525 struct AttributeStoreMessage,
2527 GNUNET_MQ_hd_fixed_size (iteration_start,
2528 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
2529 struct AttributeIterationStartMessage,
2531 GNUNET_MQ_hd_fixed_size (iteration_next,
2532 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
2533 struct AttributeIterationNextMessage,
2535 GNUNET_MQ_hd_fixed_size (iteration_stop,
2536 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
2537 struct AttributeIterationStopMessage,
2539 GNUNET_MQ_hd_var_size (issue_ticket_message,
2540 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET,
2541 struct IssueTicketMessage,
2543 GNUNET_MQ_hd_var_size (consume_ticket_message,
2544 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
2545 struct ConsumeTicketMessage,
2547 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
2548 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
2549 struct TicketIterationStartMessage,
2551 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2552 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
2553 struct TicketIterationNextMessage,
2555 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2556 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
2557 struct TicketIterationStopMessage,
2559 GNUNET_MQ_hd_var_size (revoke_ticket_message,
2560 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET,
2561 struct RevokeTicketMessage,
2563 GNUNET_MQ_handler_end());
2564 /* end of gnunet-service-identity-provider.c */