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_STATISTICS_Handle *stats_handle;
104 static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
109 static struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
114 static struct GNUNET_SCHEDULER_Task *timeout_task;
119 static struct GNUNET_SCHEDULER_Task *update_task;
123 * Currently processed token
125 static struct IdentityToken *token;
128 * Label for currently processed token
133 * Scopes for processed token
138 * Handle to the statistics service.
140 static struct GNUNET_STATISTICS_Handle *stats;
145 static const struct GNUNET_CONFIGURATION_Handle *cfg;
153 * A ticket iteration operation.
155 struct TicketIteration
160 struct TicketIteration *next;
165 struct TicketIteration *prev;
168 * Client which intiated this zone iteration
170 struct IdpClient *client;
173 * Key of the identity we are iterating over.
175 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
178 * Identity is audience
180 uint32_t is_audience;
183 * The operation id fot the iteration in the response for the client
188 * Offset of the iteration used to address next result of the
189 * iteration in the store
191 * Initialy set to 0 in handle_iteration_start
192 * Incremented with by every call to handle_iteration_next
201 * Callback after an ABE bootstrap
204 * @param abe_key the ABE key that exists or was created
207 (*AbeBootstrapResult) (void *cls,
208 struct GNUNET_CRYPTO_AbeMasterKey *abe_key);
211 struct AbeBootstrapHandle
214 * Function to call when finished
216 AbeBootstrapResult proc;
224 * Key of the zone we are iterating over.
226 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
229 * Namestore Queue Entry
231 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
234 * The issuer egos ABE master key
236 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
240 * An attribute iteration operation.
242 struct AttributeIterator
245 * Next element in the DLL
247 struct AttributeIterator *next;
250 * Previous element in the DLL
252 struct AttributeIterator *prev;
255 * IDP client which intiated this zone iteration
257 struct IdpClient *client;
260 * Key of the zone we are iterating over.
262 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
265 * The issuer egos ABE master key
267 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
272 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
275 * The operation id fot the zone iteration in the response for the client
292 struct GNUNET_SERVICE_Client *client;
295 * Message queue for transmission to @e client
297 struct GNUNET_MQ_Handle *mq;
301 * Attribute iteration operations in
302 * progress initiated by this client
304 struct AttributeIterator *op_head;
308 * Attribute iteration operations
309 * in progress initiated by this client
311 struct AttributeIterator *op_tail;
314 * Head of DLL of ticket iteration ops
316 struct TicketIteration *ticket_iter_head;
319 * Tail of DLL of ticket iteration ops
321 struct TicketIteration *ticket_iter_tail;
325 * Head of DLL of ticket revocation ops
327 struct TicketRevocationHandle *revocation_list_head;
330 * Tail of DLL of ticket revocation ops
332 struct TicketRevocationHandle *revocation_list_tail;
337 struct AttributeStoreHandle
343 struct IdpClient *client;
348 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
353 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
356 * The issuer egos ABE master key
358 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
363 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
366 * The attribute to store
368 struct GNUNET_IDENTITY_PROVIDER_Attribute *attribute;
378 struct ParallelLookup;
380 struct ConsumeTicketHandle
386 struct IdpClient *client;
391 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
396 struct GNUNET_GNS_LookupRequest *lookup_request;
401 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
406 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
411 struct ParallelLookup *parallel_lookups_head;
416 struct ParallelLookup *parallel_lookups_tail;
421 struct GNUNET_SCHEDULER_Task *kill_task;
426 struct GNUNET_CRYPTO_AbeKey *key;
431 struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
436 struct GNUNET_TIME_Absolute lookup_start_time;
445 * Handle for a parallel GNS lookup job
447 struct ParallelLookup
450 struct ParallelLookup *next;
453 struct ParallelLookup *prev;
455 /* The GNS request */
456 struct GNUNET_GNS_LookupRequest *lookup_request;
458 /* The handle the return to */
459 struct ConsumeTicketHandle *handle;
464 struct GNUNET_TIME_Absolute lookup_start_time;
466 /* The label to look up */
471 * Ticket revocation request handle
473 struct TicketRevocationHandle
478 struct TicketRevocationHandle *next;
483 struct TicketRevocationHandle *prev;
488 struct IdpClient *client;
491 * Attributes to reissue
493 struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
496 * Attributes to revoke
498 struct GNUNET_IDENTITY_PROVIDER_AttributeList *rvk_attrs;
503 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
508 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
513 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
518 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
523 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
539 * Ticket issue request handle
541 struct TicketIssueHandle
547 struct IdpClient *client;
550 * Attributes to issue
552 struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
557 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
562 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
567 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
577 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
585 struct EgoEntry *next;
590 struct EgoEntry *prev;
595 struct GNUNET_IDENTITY_Ego *ego;
598 * Attribute map. Contains the attributes as json_t
600 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
610 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
614 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
617 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
619 GNUNET_free (db_lib_name);
621 if (NULL != timeout_task)
622 GNUNET_SCHEDULER_cancel (timeout_task);
623 if (NULL != update_task)
624 GNUNET_SCHEDULER_cancel (update_task);
625 if (NULL != identity_handle)
626 GNUNET_IDENTITY_disconnect (identity_handle);
627 if (NULL != gns_handle)
628 GNUNET_GNS_disconnect (gns_handle);
629 if (NULL != credential_handle)
630 GNUNET_CREDENTIAL_disconnect (credential_handle);
632 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
634 GNUNET_NAMESTORE_cancel (ns_qe);
635 if (NULL != ns_handle)
636 GNUNET_NAMESTORE_disconnect (ns_handle);
637 if (NULL != stats_handle)
638 GNUNET_STATISTICS_destroy (stats_handle, GNUNET_NO);
650 * @param tc task context
653 do_shutdown (void *cls)
655 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
656 "Shutting down...\n");
661 * Finished storing newly bootstrapped ABE key
664 bootstrap_store_cont (void *cls,
668 struct AbeBootstrapHandle *abh = cls;
669 if (GNUNET_SYSERR == success)
671 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
672 "Failed to bootstrap ABE master %s\n",
674 abh->proc (abh->proc_cls, NULL);
675 GNUNET_free (abh->abe_key);
679 abh->proc (abh->proc_cls, abh->abe_key);
684 * Generates and stores a new ABE key
687 bootstrap_store_task (void *cls)
689 struct AbeBootstrapHandle *abh = cls;
690 struct GNUNET_GNSRECORD_Data rd[1];
693 rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (abh->abe_key,
696 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
697 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
698 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
699 abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
704 &bootstrap_store_cont,
710 * Error checking for ABE master
713 bootstrap_abe_error (void *cls)
715 struct AbeBootstrapHandle *abh = cls;
717 abh->proc (abh->proc_cls, NULL);
723 * Handle ABE lookup in namestore
726 bootstrap_abe_result (void *cls,
727 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
729 unsigned int rd_count,
730 const struct GNUNET_GNSRECORD_Data *rd)
732 struct AbeBootstrapHandle *abh = cls;
733 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
736 for (i=0;i<rd_count;i++) {
737 if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
739 abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key (rd[i].data,
741 abh->proc (abh->proc_cls, abe_key);
746 //No ABE master found, bootstrapping...
747 abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
748 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
752 * Bootstrap ABE master if it does not yet exists.
753 * Will call the AbeBootstrapResult processor when done.
754 * will always recreate the ABE key of GNUNET_YES == recreate
757 bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
758 AbeBootstrapResult proc,
762 struct AbeBootstrapHandle *abh;
764 abh = GNUNET_new (struct AbeBootstrapHandle);
767 abh->identity = *identity;
768 if (GNUNET_YES == recreate)
770 abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
771 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
773 abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
776 &bootstrap_abe_error,
778 &bootstrap_abe_result,
786 create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
787 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
788 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
790 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
792 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
794 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
795 static const char ctx_key[] = "gnuid-aes-ctx-key";
796 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
797 new_key_hash, sizeof (struct GNUNET_HashCode),
798 ctx_key, strlen (ctx_key),
800 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
801 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
802 new_key_hash, sizeof (struct GNUNET_HashCode),
803 ctx_iv, strlen (ctx_iv),
809 cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
811 if (NULL != handle->attrs)
812 attribute_list_destroy (handle->attrs);
813 if (NULL != handle->ns_qe)
814 GNUNET_NAMESTORE_cancel (handle->ns_qe);
815 GNUNET_free (handle);
820 send_ticket_result (struct IdpClient *client,
822 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
823 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
825 struct TicketResultMessage *irm;
826 struct GNUNET_MQ_Envelope *env;
827 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
829 /* store ticket in DB */
830 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
834 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
835 "Unable to store ticket after issue\n");
839 env = GNUNET_MQ_msg_extra (irm,
840 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
841 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
842 ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
843 *ticket_buf = *ticket;
844 irm->id = htonl (r_id);
845 GNUNET_MQ_send (client->mq,
850 store_ticket_issue_cont (void *cls,
854 struct TicketIssueHandle *handle = cls;
856 handle->ns_qe = NULL;
857 if (GNUNET_SYSERR == success)
859 cleanup_ticket_issue_handle (handle);
860 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
862 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
865 send_ticket_result (handle->client,
869 cleanup_ticket_issue_handle (handle);
875 serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
876 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs,
877 const struct GNUNET_CRYPTO_AbeKey *rp_key,
878 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
881 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
882 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
884 char *serialized_key;
890 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
891 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
892 struct GNUNET_HashCode new_key_hash;
895 size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key,
896 (void**)&serialized_key);
898 for (le = attrs->list_head; NULL != le; le = le->next) {
899 attrs_str_len += strlen (le->attribute->name) + 1;
901 buf = GNUNET_malloc (attrs_str_len + size);
903 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
904 "Writing attributes\n");
905 for (le = attrs->list_head; NULL != le; le = le->next) {
906 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
907 "%s\n", le->attribute->name);
910 GNUNET_memcpy (write_ptr,
912 strlen (le->attribute->name));
913 write_ptr[strlen (le->attribute->name)] = ',';
914 write_ptr += strlen (le->attribute->name) + 1;
917 write_ptr[0] = '\0'; //replace last , with a 0-terminator
919 GNUNET_memcpy (write_ptr,
922 GNUNET_free (serialized_key);
923 // ECDH keypair E = eG
924 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
925 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
927 enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
928 // Derived key K = H(eB)
929 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
932 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
933 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
934 size + attrs_str_len,
937 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
939 GNUNET_memcpy (*result,
941 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
942 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
945 GNUNET_free (enc_keyinfo);
947 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
953 issue_ticket_after_abe_bootstrap (void *cls,
954 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
956 struct TicketIssueHandle *ih = cls;
957 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
958 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
959 struct GNUNET_GNSRECORD_Data code_record[1];
960 struct GNUNET_CRYPTO_AbeKey *rp_key;
961 char *code_record_data;
967 size_t code_record_len;
969 //Create new ABE key for RP
971 for (le = ih->attrs->list_head; NULL != le; le = le->next)
973 attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
975 for (le = ih->attrs->list_head; NULL != le; le = le->next) {
976 GNUNET_asprintf (&policy, "%s_%lu",
978 le->attribute->attribute_version);
979 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
980 "Adding attribute to key: %s\n",
986 rp_key = GNUNET_CRYPTO_cpabe_create_key (abe_key,
989 //TODO review this wireformat
990 code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
995 code_record[0].data = code_record_data;
996 code_record[0].data_size = code_record_len;
997 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
998 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
999 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1001 label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
1004 ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1009 &store_ticket_issue_cont,
1011 //for (; i > 0; i--)
1012 // GNUNET_free (attrs[i-1]);
1013 GNUNET_free (ecdhe_privkey);
1014 GNUNET_free (label);
1015 GNUNET_free (attrs);
1016 GNUNET_free (code_record_data);
1017 GNUNET_CRYPTO_cpabe_delete_key (rp_key,
1019 GNUNET_CRYPTO_cpabe_delete_master_key (abe_key);
1024 * Checks a ticket issue message
1026 * @param cls client sending the message
1027 * @param im message of type `struct TicketIssueMessage`
1028 * @return #GNUNET_OK if @a im is well-formed
1031 check_issue_ticket_message(void *cls,
1032 const struct IssueTicketMessage *im)
1036 size = ntohs (im->header.size);
1037 if (size <= sizeof (struct IssueTicketMessage))
1040 return GNUNET_SYSERR;
1048 * Handler for ticket issue message
1051 * @param client who sent the message
1052 * @param message the message
1055 handle_issue_ticket_message (void *cls,
1056 const struct IssueTicketMessage *im)
1058 struct TicketIssueHandle *ih;
1059 struct IdpClient *idp = cls;
1062 ih = GNUNET_new (struct TicketIssueHandle);
1063 attrs_len = ntohs (im->attr_len);
1064 ih->attrs = attribute_list_deserialize ((char*)&im[1], attrs_len);
1065 ih->r_id = ntohl (im->id);
1067 ih->identity = im->identity;
1068 GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
1069 &ih->ticket.identity);
1070 ih->ticket.audience = im->rp;
1072 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1074 bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
1075 GNUNET_SERVICE_client_continue (idp->client);
1079 /**********************************************************
1081 **********************************************************/
1084 * Cleanup revoke handle
1087 cleanup_revoke_ticket_handle (struct TicketRevocationHandle *handle)
1089 if (NULL != handle->attrs)
1090 attribute_list_destroy (handle->attrs);
1091 if (NULL != handle->rvk_attrs)
1092 attribute_list_destroy (handle->rvk_attrs);
1093 if (NULL != handle->abe_key)
1094 GNUNET_CRYPTO_cpabe_delete_master_key (handle->abe_key);
1095 if (NULL != handle->ns_qe)
1096 GNUNET_NAMESTORE_cancel (handle->ns_qe);
1097 if (NULL != handle->ns_it)
1098 GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
1099 GNUNET_free (handle);
1104 * Send revocation result
1107 send_revocation_finished (struct TicketRevocationHandle *rh,
1110 struct GNUNET_MQ_Envelope *env;
1111 struct RevokeTicketResultMessage *trm;
1113 env = GNUNET_MQ_msg (trm,
1114 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT);
1115 trm->id = htonl (rh->r_id);
1116 trm->success = htonl (success);
1117 GNUNET_MQ_send (rh->client->mq,
1119 GNUNET_CONTAINER_DLL_remove (rh->client->revocation_list_head,
1120 rh->client->revocation_list_tail,
1126 * Process ticket from database
1128 * @param cls struct TicketIterationProcResult
1129 * @param ticket the ticket
1130 * @param attrs the attributes
1133 ticket_reissue_proc (void *cls,
1134 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1135 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs);
1138 revocation_reissue_tickets (struct TicketRevocationHandle *rh);
1141 static void reissue_next (void *cls)
1143 struct TicketRevocationHandle *rh = cls;
1144 revocation_reissue_tickets (rh);
1149 reissue_ticket_cont (void *cls,
1153 struct TicketRevocationHandle *rh = cls;
1156 if (GNUNET_SYSERR == success)
1158 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1160 send_revocation_finished (rh, GNUNET_SYSERR);
1161 cleanup_revoke_ticket_handle (rh);
1165 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
1170 * Process ticket from database
1172 * @param cls struct TicketIterationProcResult
1173 * @param ticket the ticket
1174 * @param attrs the attributes
1177 ticket_reissue_proc (void *cls,
1178 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1179 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
1181 struct TicketRevocationHandle *rh = cls;
1182 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1183 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le_rollover;
1184 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
1185 struct GNUNET_GNSRECORD_Data code_record[1];
1186 struct GNUNET_CRYPTO_AbeKey *rp_key;
1187 char *code_record_data;
1194 size_t code_record_len;
1199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1200 "Iteration done\n");
1204 if (0 == memcmp (&ticket->audience,
1205 &rh->ticket.audience,
1206 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
1208 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1209 "Do not reissue for this identity.!\n");
1212 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
1217 * Check if any attribute of this ticket intersects with a rollover attribute
1219 reissue_ticket = GNUNET_NO;
1220 for (le = attrs->list_head; NULL != le; le = le->next)
1222 for (le_rollover = rh->rvk_attrs->list_head;
1223 NULL != le_rollover;
1224 le_rollover = le_rollover->next)
1226 if (0 == strcmp (le_rollover->attribute->name,
1227 le->attribute->name))
1229 reissue_ticket = GNUNET_YES;
1230 le->attribute->attribute_version = le_rollover->attribute->attribute_version;
1235 if (GNUNET_NO == reissue_ticket)
1237 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1238 "Skipping ticket.\n");
1241 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
1247 //Create new ABE key for RP
1250 /* If this is the RP we want to revoke attributes of, the do so */
1252 for (le = attrs->list_head; NULL != le; le = le->next)
1254 attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1256 for (le = attrs->list_head; NULL != le; le = le->next) {
1257 GNUNET_asprintf (&policy, "%s_%lu",
1258 le->attribute->name,
1259 le->attribute->attribute_version);
1260 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1261 "Recreating key with %s\n", policy);
1262 attr_arr[i] = policy;
1266 rp_key = GNUNET_CRYPTO_cpabe_create_key (rh->abe_key,
1269 //TODO review this wireformat
1270 code_record_len = serialize_abe_keyinfo2 (ticket,
1275 code_record[0].data = code_record_data;
1276 code_record[0].data_size = code_record_len;
1277 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1278 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1279 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1281 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
1284 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1289 &reissue_ticket_cont,
1291 //for (; i > 0; i--)
1292 // GNUNET_free (attr_arr[i-1]);
1293 GNUNET_free (ecdhe_privkey);
1294 GNUNET_free (label);
1295 GNUNET_free (attr_arr);
1296 GNUNET_free (code_record_data);
1297 GNUNET_CRYPTO_cpabe_delete_key (rp_key, GNUNET_YES);
1301 /* Prototype for below function */
1303 attr_reenc_cont (void *cls,
1308 revocation_reissue_tickets (struct TicketRevocationHandle *rh)
1311 /* Done, issue new keys */
1312 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1313 "Revocation Phase III: Reissuing Tickets\n");
1314 if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
1315 &rh->ticket.identity,
1318 &ticket_reissue_proc,
1323 if (GNUNET_NO == ret)
1325 send_revocation_finished (rh, GNUNET_OK);
1326 cleanup_revoke_ticket_handle (rh);
1332 * Revoke next attribte by reencryption with
1336 reenc_next_attribute (struct TicketRevocationHandle *rh)
1338 struct GNUNET_GNSRECORD_Data rd[1];
1347 if (NULL == rh->attrs->list_head)
1349 revocation_reissue_tickets (rh);
1352 buf_size = attribute_serialize_get_size (rh->attrs->list_head->attribute);
1353 buf = GNUNET_malloc (buf_size);
1354 attribute_serialize (rh->attrs->list_head->attribute,
1356 rh->attrs->list_head->attribute->attribute_version++;
1357 GNUNET_asprintf (&policy, "%s_%lu",
1358 rh->attrs->list_head->attribute->name,
1359 rh->attrs->list_head->attribute->attribute_version);
1360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1361 "Encrypting with policy %s\n", policy);
1363 * Encrypt the attribute value and store in namestore
1365 enc_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1371 GNUNET_free (policy);
1372 rd[0].data_size = enc_size + sizeof (uint32_t);
1373 rd_buf = GNUNET_malloc (rd[0].data_size);
1374 attr_ver = htonl (rh->attrs->list_head->attribute->attribute_version);
1375 GNUNET_memcpy (rd_buf,
1378 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1381 rd[0].data = rd_buf;
1382 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1383 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1384 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1385 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1387 rh->attrs->list_head->attribute->name,
1392 GNUNET_free (enc_buf);
1393 GNUNET_free (rd_buf);
1397 * Namestore callback after revoked attribute
1401 attr_reenc_cont (void *cls,
1405 struct TicketRevocationHandle *rh = cls;
1406 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1408 if (GNUNET_SYSERR == success)
1410 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1411 "Failed to reencrypt attribute %s\n",
1413 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1416 if (NULL == rh->attrs->list_head)
1418 revocation_reissue_tickets (rh);
1421 le = rh->attrs->list_head;
1422 GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1423 rh->attrs->list_tail,
1425 GNUNET_assert (NULL != rh->rvk_attrs);
1426 GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
1427 rh->rvk_attrs->list_tail,
1431 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1432 "Re-encrypting next attribute\n");
1433 reenc_next_attribute (rh);
1438 process_attributes_to_update (void *cls,
1439 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1440 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
1442 struct TicketRevocationHandle *rh = cls;
1444 rh->attrs = attribute_list_dup (attrs);
1445 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1446 "Revocation Phase I: Collecting attributes\n");
1447 /* Reencrypt all attributes with new key */
1448 if (NULL == rh->attrs->list_head)
1450 /* No attributes to reencrypt */
1451 send_revocation_finished (rh, GNUNET_OK);
1452 cleanup_revoke_ticket_handle (rh);
1455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1456 "Revocation Phase II: Re-encrypting attributes\n");
1457 reenc_next_attribute (rh);
1465 get_ticket_after_abe_bootstrap (void *cls,
1466 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1468 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1469 "Finished ABE bootstrap\n");
1470 struct TicketRevocationHandle *rh = cls;
1471 rh->abe_key = abe_key;
1472 TKT_database->get_ticket_attributes (TKT_database->cls,
1474 &process_attributes_to_update,
1479 * Checks a ticket revocation message
1481 * @param cls client sending the message
1482 * @param im message of type `struct RevokeTicketMessage`
1483 * @return #GNUNET_OK if @a im is well-formed
1486 check_revoke_ticket_message(void *cls,
1487 const struct RevokeTicketMessage *im)
1491 size = ntohs (im->header.size);
1492 if (size <= sizeof (struct RevokeTicketMessage))
1495 return GNUNET_SYSERR;
1501 * Handler for ticket revocation message
1504 * @param client who sent the message
1505 * @param message the message
1508 handle_revoke_ticket_message (void *cls,
1509 const struct RevokeTicketMessage *rm)
1511 struct TicketRevocationHandle *rh;
1512 struct IdpClient *idp = cls;
1513 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
1515 rh = GNUNET_new (struct TicketRevocationHandle);
1516 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1];
1517 rh->rvk_attrs = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
1518 rh->ticket = *ticket;
1519 rh->r_id = ntohl (rm->id);
1521 rh->identity = rm->identity;
1522 GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
1523 &rh->ticket.identity);
1524 GNUNET_CONTAINER_DLL_insert (idp->revocation_list_head,
1525 idp->revocation_list_tail,
1527 bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO);
1528 GNUNET_SERVICE_client_continue (idp->client);
1534 cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
1536 if (NULL != handle->key)
1537 GNUNET_CRYPTO_cpabe_delete_key (handle->key,
1539 if (NULL != handle->attrs)
1540 attribute_list_destroy (handle->attrs);
1541 GNUNET_free (handle);
1547 * Checks a ticket consume message
1549 * @param cls client sending the message
1550 * @param im message of type `struct ConsumeTicketMessage`
1551 * @return #GNUNET_OK if @a im is well-formed
1554 check_consume_ticket_message(void *cls,
1555 const struct ConsumeTicketMessage *cm)
1559 size = ntohs (cm->header.size);
1560 if (size <= sizeof (struct ConsumeTicketMessage))
1563 return GNUNET_SYSERR;
1569 process_parallel_lookup2 (void *cls, uint32_t rd_count,
1570 const struct GNUNET_GNSRECORD_Data *rd)
1572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1573 "Parallel lookup finished (count=%u)\n", rd_count);
1574 struct ParallelLookup *parallel_lookup = cls;
1575 struct ConsumeTicketHandle *handle = parallel_lookup->handle;
1576 struct ConsumeTicketResultMessage *crm;
1577 struct GNUNET_MQ_Envelope *env;
1578 struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *attr_le;
1579 struct GNUNET_TIME_Absolute decrypt_duration;
1585 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1586 handle->parallel_lookups_tail,
1588 GNUNET_free (parallel_lookup->label);
1590 GNUNET_STATISTICS_update (stats_handle,
1591 "attribute_lookup_time_total",
1592 GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us,
1594 GNUNET_STATISTICS_update (stats_handle,
1595 "attribute_lookups_count",
1600 GNUNET_free (parallel_lookup);
1602 GNUNET_break(0);//TODO
1603 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1605 decrypt_duration = GNUNET_TIME_absolute_get ();
1606 attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data + sizeof (uint32_t),
1607 rd->data_size - sizeof (uint32_t),
1610 if (GNUNET_SYSERR != attr_len)
1612 GNUNET_STATISTICS_update (stats_handle,
1613 "abe_decrypt_time_total",
1614 GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us,
1616 GNUNET_STATISTICS_update (stats_handle,
1617 "abe_decrypt_count",
1621 attr_le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
1622 attr_le->attribute = attribute_deserialize (data,
1624 attr_le->attribute->attribute_version = ntohl(*(uint32_t*)rd->data);
1625 GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
1626 handle->attrs->list_tail,
1631 if (NULL != handle->parallel_lookups_head)
1632 return; //Wait for more
1633 /* Else we are done */
1635 /* Store ticket in DB */
1636 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1640 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1641 "Unable to store ticket after consume\n");
1645 GNUNET_SCHEDULER_cancel (handle->kill_task);
1646 attrs_len = attribute_list_serialize_get_size (handle->attrs);
1647 env = GNUNET_MQ_msg_extra (crm,
1649 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
1650 crm->id = htonl (handle->r_id);
1651 crm->attrs_len = htons (attrs_len);
1652 crm->identity = handle->ticket.identity;
1653 data_tmp = (char *) &crm[1];
1654 attribute_list_serialize (handle->attrs,
1656 GNUNET_MQ_send (handle->client->mq, env);
1657 cleanup_consume_ticket_handle (handle);
1661 abort_parallel_lookups2 (void *cls)
1663 struct ConsumeTicketHandle *handle = cls;
1664 struct ParallelLookup *lu;
1665 struct ParallelLookup *tmp;
1666 struct AttributeResultMessage *arm;
1667 struct GNUNET_MQ_Envelope *env;
1669 for (lu = handle->parallel_lookups_head;
1671 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1672 GNUNET_free (lu->label);
1674 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1675 handle->parallel_lookups_tail,
1680 env = GNUNET_MQ_msg (arm,
1681 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1682 arm->id = htonl (handle->r_id);
1683 arm->attr_len = htons (0);
1684 GNUNET_MQ_send (handle->client->mq, env);
1690 process_consume_abe_key (void *cls, uint32_t rd_count,
1691 const struct GNUNET_GNSRECORD_Data *rd)
1693 struct ConsumeTicketHandle *handle = cls;
1694 struct GNUNET_HashCode new_key_hash;
1695 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1696 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1697 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1698 struct ParallelLookup *parallel_lookup;
1704 handle->lookup_request = NULL;
1707 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1708 "Number of keys %d != 1.",
1710 cleanup_consume_ticket_handle (handle);
1711 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1716 ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1718 buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1720 //Calculate symmetric key from ecdh parameters
1721 GNUNET_assert (GNUNET_OK ==
1722 GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
1725 create_sym_key_from_ecdh (&new_key_hash,
1728 size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1729 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1734 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1735 "Decrypted bytes: %zd Expected bytes: %zd\n",
1736 size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1737 GNUNET_STATISTICS_update (stats_handle,
1738 "abe_key_lookup_time_total",
1739 GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us,
1741 GNUNET_STATISTICS_update (stats_handle,
1742 "abe_key_lookups_count",
1745 scopes = GNUNET_strdup (buf);
1746 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1747 "Scopes %s\n", scopes);
1748 handle->key = GNUNET_CRYPTO_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1749 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1750 - strlen (scopes) - 1);
1752 for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1754 GNUNET_asprintf (&lookup_query,
1757 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1758 "Looking up %s\n", lookup_query);
1759 parallel_lookup = GNUNET_new (struct ParallelLookup);
1760 parallel_lookup->handle = handle;
1761 parallel_lookup->label = GNUNET_strdup (scope);
1762 parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get();
1763 parallel_lookup->lookup_request
1764 = GNUNET_GNS_lookup (gns_handle,
1766 &handle->ticket.identity,
1767 GNUNET_GNSRECORD_TYPE_ID_ATTR,
1768 GNUNET_GNS_LO_DEFAULT,
1769 &process_parallel_lookup2,
1771 GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1772 handle->parallel_lookups_tail,
1774 GNUNET_free (lookup_query);
1776 GNUNET_free (scopes);
1778 handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1779 &abort_parallel_lookups2,
1786 * Handler for ticket issue message
1789 * @param client who sent the message
1790 * @param message the message
1793 handle_consume_ticket_message (void *cls,
1794 const struct ConsumeTicketMessage *cm)
1796 struct ConsumeTicketHandle *ch;
1797 struct IdpClient *idp = cls;
1801 ch = GNUNET_new (struct ConsumeTicketHandle);
1802 ch->r_id = ntohl (cm->id);
1804 ch->identity = cm->identity;
1805 ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
1806 GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
1808 ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
1809 rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
1811 GNUNET_asprintf (&lookup_query,
1814 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1815 "Looking for ABE key under %s\n", lookup_query);
1816 ch->lookup_start_time = GNUNET_TIME_absolute_get ();
1818 = GNUNET_GNS_lookup (gns_handle,
1820 &ch->ticket.identity,
1821 GNUNET_GNSRECORD_TYPE_ABE_KEY,
1822 GNUNET_GNS_LO_DEFAULT,
1823 &process_consume_abe_key,
1825 GNUNET_free (rnd_label);
1826 GNUNET_free (lookup_query);
1827 GNUNET_SERVICE_client_continue (idp->client);
1831 cleanup_as_handle (struct AttributeStoreHandle *handle)
1833 if (NULL != handle->attribute)
1834 GNUNET_free (handle->attribute);
1835 if (NULL != handle->abe_key)
1836 GNUNET_CRYPTO_cpabe_delete_master_key (handle->abe_key);
1837 GNUNET_free (handle);
1841 attr_store_cont (void *cls,
1845 struct AttributeStoreHandle *as_handle = cls;
1846 struct GNUNET_MQ_Envelope *env;
1847 struct AttributeStoreResultMessage *acr_msg;
1849 if (GNUNET_SYSERR == success)
1851 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1852 "Failed to store attribute %s\n",
1854 cleanup_as_handle (as_handle);
1855 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1860 "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1861 env = GNUNET_MQ_msg (acr_msg,
1862 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
1863 acr_msg->id = htonl (as_handle->r_id);
1864 acr_msg->op_result = htonl (GNUNET_OK);
1865 GNUNET_MQ_send (as_handle->client->mq,
1867 cleanup_as_handle (as_handle);
1871 attr_store_task (void *cls)
1873 struct AttributeStoreHandle *as_handle = cls;
1874 struct GNUNET_GNSRECORD_Data rd[1];
1883 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1884 "Storing attribute\n");
1885 buf_size = attribute_serialize_get_size (as_handle->attribute);
1886 buf = GNUNET_malloc (buf_size);
1888 attribute_serialize (as_handle->attribute,
1891 GNUNET_asprintf (&policy,
1893 as_handle->attribute->name,
1894 as_handle->attribute->attribute_version);
1895 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1896 "Encrypting with policy %s\n", policy);
1898 * Encrypt the attribute value and store in namestore
1900 enc_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1906 GNUNET_free (policy);
1907 rd[0].data_size = enc_size + sizeof (uint32_t);
1908 rd_buf = GNUNET_malloc (rd[0].data_size);
1909 attr_ver = htonl (as_handle->attribute->attribute_version);
1910 GNUNET_memcpy (rd_buf,
1913 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1916 rd[0].data = rd_buf;
1917 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1918 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1919 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1920 as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1921 &as_handle->identity,
1922 as_handle->attribute->name,
1927 GNUNET_free (enc_buf);
1928 GNUNET_free (rd_buf);
1933 store_after_abe_bootstrap (void *cls,
1934 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1936 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1937 "Finished ABE bootstrap\n");
1938 struct AttributeStoreHandle *ash = cls;
1939 ash->abe_key = abe_key;
1940 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1944 * Checks a store message
1946 * @param cls client sending the message
1947 * @param sam message of type `struct AttributeStoreMessage`
1948 * @return #GNUNET_OK if @a im is well-formed
1951 check_attribute_store_message(void *cls,
1952 const struct AttributeStoreMessage *sam)
1956 size = ntohs (sam->header.size);
1957 if (size <= sizeof (struct AttributeStoreMessage))
1960 return GNUNET_SYSERR;
1968 * Handler for store message
1971 * @param client who sent the message
1972 * @param message the message
1975 handle_attribute_store_message (void *cls,
1976 const struct AttributeStoreMessage *sam)
1978 struct AttributeStoreHandle *as_handle;
1979 struct IdpClient *idp = cls;
1981 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1982 "Received ATTRIBUTE_STORE message\n");
1984 data_len = ntohs (sam->attr_len);
1986 as_handle = GNUNET_new (struct AttributeStoreHandle);
1987 as_handle->attribute = attribute_deserialize ((char*)&sam[1],
1990 as_handle->r_id = ntohl (sam->id);
1991 as_handle->identity = sam->identity;
1992 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1993 &as_handle->identity_pkey);
1995 GNUNET_SERVICE_client_continue (idp->client);
1996 as_handle->client = idp;
1997 bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
2001 cleanup_iter_handle (struct AttributeIterator *ai)
2003 if (NULL != ai->abe_key)
2004 GNUNET_CRYPTO_cpabe_delete_master_key (ai->abe_key);
2005 GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
2006 ai->client->op_tail,
2012 attr_iter_error (void *cls)
2014 struct AttributeIterator *ai = cls;
2016 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2017 "Failed to iterate over attributes\n");
2018 cleanup_iter_handle (ai);
2019 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
2023 attr_iter_finished (void *cls)
2025 struct AttributeIterator *ai = cls;
2026 struct GNUNET_MQ_Envelope *env;
2027 struct AttributeResultMessage *arm;
2029 env = GNUNET_MQ_msg (arm,
2030 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
2031 arm->id = htonl (ai->request_id);
2032 arm->attr_len = htons (0);
2033 GNUNET_MQ_send (ai->client->mq, env);
2034 cleanup_iter_handle (ai);
2038 attr_iter_cb (void *cls,
2039 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
2041 unsigned int rd_count,
2042 const struct GNUNET_GNSRECORD_Data *rd)
2044 struct AttributeIterator *ai = cls;
2045 struct AttributeResultMessage *arm;
2046 struct GNUNET_CRYPTO_AbeKey *key;
2047 struct GNUNET_MQ_Envelope *env;
2048 ssize_t msg_extra_len;
2057 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2061 if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
2062 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2065 attr_ver = ntohl(*((uint32_t*)rd->data));
2066 GNUNET_asprintf (&policy, "%s_%lu",
2070 key = GNUNET_CRYPTO_cpabe_create_key (ai->abe_key,
2072 msg_extra_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data+sizeof (uint32_t),
2073 rd->data_size-sizeof (uint32_t),
2077 GNUNET_CRYPTO_cpabe_delete_key (key,
2079 //GNUNET_free (policy);
2080 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2081 "Found attribute: %s\n", label);
2082 env = GNUNET_MQ_msg_extra (arm,
2084 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
2085 arm->id = htonl (ai->request_id);
2086 arm->attr_len = htons (msg_extra_len);
2087 GNUNET_CRYPTO_ecdsa_key_get_public (zone,
2089 data_tmp = (char *) &arm[1];
2090 GNUNET_memcpy (data_tmp,
2093 GNUNET_MQ_send (ai->client->mq, env);
2094 GNUNET_free (attr_ser);
2095 GNUNET_CRYPTO_cpabe_delete_master_key (ai->abe_key);
2101 iterate_after_abe_bootstrap (void *cls,
2102 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
2104 struct AttributeIterator *ai = cls;
2105 ai->abe_key = abe_key;
2106 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
2112 &attr_iter_finished,
2117 iterate_next_after_abe_bootstrap (void *cls,
2118 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
2120 struct AttributeIterator *ai = cls;
2121 ai->abe_key = abe_key;
2122 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2128 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_START message
2130 * @param cls the client sending the message
2131 * @param zis_msg message from the client
2134 handle_iteration_start (void *cls,
2135 const struct AttributeIterationStartMessage *ais_msg)
2137 struct IdpClient *idp = cls;
2138 struct AttributeIterator *ai;
2140 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2141 "Received ATTRIBUTE_ITERATION_START message\n");
2142 ai = GNUNET_new (struct AttributeIterator);
2143 ai->request_id = ntohl (ais_msg->id);
2145 ai->identity = ais_msg->identity;
2147 GNUNET_CONTAINER_DLL_insert (idp->op_head,
2150 bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
2151 GNUNET_SERVICE_client_continue (idp->client);
2156 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_STOP message
2158 * @param cls the client sending the message
2159 * @param ais_msg message from the client
2162 handle_iteration_stop (void *cls,
2163 const struct AttributeIterationStopMessage *ais_msg)
2165 struct IdpClient *idp = cls;
2166 struct AttributeIterator *ai;
2169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2170 "Received `%s' message\n",
2171 "ATTRIBUTE_ITERATION_STOP");
2172 rid = ntohl (ais_msg->id);
2173 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2174 if (ai->request_id == rid)
2179 GNUNET_SERVICE_client_drop (idp->client);
2182 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2186 GNUNET_SERVICE_client_continue (idp->client);
2191 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT message
2193 * @param cls the client sending the message
2194 * @param message message from the client
2197 handle_iteration_next (void *cls,
2198 const struct AttributeIterationNextMessage *ais_msg)
2200 struct IdpClient *idp = cls;
2201 struct AttributeIterator *ai;
2204 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2205 "Received ATTRIBUTE_ITERATION_NEXT message\n");
2206 rid = ntohl (ais_msg->id);
2207 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2208 if (ai->request_id == rid)
2213 GNUNET_SERVICE_client_drop (idp->client);
2216 bootstrap_abe (&ai->identity,
2217 &iterate_next_after_abe_bootstrap,
2220 GNUNET_SERVICE_client_continue (idp->client);
2224 * Ticket iteration processor result
2226 enum ZoneIterationResult
2235 * Continue to iterate with next iteration_next call
2237 IT_SUCCESS_MORE_AVAILABLE = 1,
2240 * Iteration complete
2242 IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
2247 * Context for ticket iteration
2249 struct TicketIterationProcResult
2252 * The ticket iteration handle
2254 struct TicketIteration *ti;
2257 * Iteration result: iteration done?
2258 * #IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but
2259 * we got one for now and have sent it to the client
2260 * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
2261 * #IT_START: if we are still trying to find a result.
2263 int res_iteration_finished;
2268 cleanup_ticket_iter_handle (struct TicketIteration *ti)
2274 * Process ticket from database
2276 * @param cls struct TicketIterationProcResult
2277 * @param ticket the ticket
2278 * @param attrs the attributes
2281 ticket_iterate_proc (void *cls,
2282 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
2283 const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
2285 struct TicketIterationProcResult *proc = cls;
2289 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2290 "Iteration done\n");
2291 proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2294 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
2295 send_ticket_result (proc->ti->client,
2303 * Perform ticket iteration step
2305 * @param ti ticket iterator to process
2308 run_ticket_iteration_round (struct TicketIteration *ti)
2310 struct TicketIterationProcResult proc;
2311 struct GNUNET_MQ_Envelope *env;
2312 struct TicketResultMessage *trm;
2315 memset (&proc, 0, sizeof (proc));
2317 proc.res_iteration_finished = IT_START;
2318 while (IT_START == proc.res_iteration_finished)
2320 if (GNUNET_SYSERR ==
2321 (ret = TKT_database->iterate_tickets (TKT_database->cls,
2325 &ticket_iterate_proc,
2331 if (GNUNET_NO == ret)
2332 proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2335 if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
2337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2338 "More results available\n");
2339 return; /* more later */
2341 /* send empty response to indicate end of list */
2342 env = GNUNET_MQ_msg (trm,
2343 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
2344 trm->id = htonl (ti->r_id);
2345 GNUNET_MQ_send (ti->client->mq,
2347 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2348 ti->client->ticket_iter_tail,
2350 cleanup_ticket_iter_handle (ti);
2354 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START message
2356 * @param cls the client sending the message
2357 * @param tis_msg message from the client
2360 handle_ticket_iteration_start (void *cls,
2361 const struct TicketIterationStartMessage *tis_msg)
2363 struct IdpClient *client = cls;
2364 struct TicketIteration *ti;
2366 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2367 "Received TICKET_ITERATION_START message\n");
2368 ti = GNUNET_new (struct TicketIteration);
2369 ti->r_id = ntohl (tis_msg->id);
2371 ti->client = client;
2372 ti->identity = tis_msg->identity;
2373 ti->is_audience = ntohl (tis_msg->is_audience);
2375 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2376 client->ticket_iter_tail,
2378 run_ticket_iteration_round (ti);
2379 GNUNET_SERVICE_client_continue (client->client);
2384 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP message
2386 * @param cls the client sending the message
2387 * @param tis_msg message from the client
2390 handle_ticket_iteration_stop (void *cls,
2391 const struct TicketIterationStopMessage *tis_msg)
2393 struct IdpClient *client = cls;
2394 struct TicketIteration *ti;
2397 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2398 "Received `%s' message\n",
2399 "TICKET_ITERATION_STOP");
2400 rid = ntohl (tis_msg->id);
2401 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2402 if (ti->r_id == rid)
2407 GNUNET_SERVICE_client_drop (client->client);
2410 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2411 client->ticket_iter_tail,
2413 cleanup_ticket_iter_handle (ti);
2414 GNUNET_SERVICE_client_continue (client->client);
2419 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT message
2421 * @param cls the client sending the message
2422 * @param message message from the client
2425 handle_ticket_iteration_next (void *cls,
2426 const struct TicketIterationNextMessage *tis_msg)
2428 struct IdpClient *client = cls;
2429 struct TicketIteration *ti;
2432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2433 "Received TICKET_ITERATION_NEXT message\n");
2434 rid = ntohl (tis_msg->id);
2435 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2436 if (ti->r_id == rid)
2441 GNUNET_SERVICE_client_drop (client->client);
2444 run_ticket_iteration_round (ti);
2445 GNUNET_SERVICE_client_continue (client->client);
2452 * Main function that will be run
2454 * @param cls closure
2455 * @param args remaining command-line arguments
2456 * @param cfgfile name of the configuration file used (for saving, can be NULL)
2457 * @param c configuration
2461 const struct GNUNET_CONFIGURATION_Handle *c,
2462 struct GNUNET_SERVICE_Handle *server)
2467 stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
2469 //Connect to identity and namestore services
2470 ns_handle = GNUNET_NAMESTORE_connect (cfg);
2471 if (NULL == ns_handle)
2473 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
2476 gns_handle = GNUNET_GNS_connect (cfg);
2477 if (NULL == gns_handle)
2479 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
2481 credential_handle = GNUNET_CREDENTIAL_connect (cfg);
2482 if (NULL == credential_handle)
2484 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
2486 identity_handle = GNUNET_IDENTITY_connect (cfg,
2489 stats_handle = GNUNET_STATISTICS_create ("identity-provider",
2491 /* Loading DB plugin */
2493 GNUNET_CONFIGURATION_get_value_string (cfg,
2494 "identity-provider",
2497 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2498 "No database backend configured\n");
2499 GNUNET_asprintf (&db_lib_name,
2500 "libgnunet_plugin_identity_provider_%s",
2502 TKT_database = GNUNET_PLUGIN_load (db_lib_name,
2504 GNUNET_free (database);
2505 if (NULL == TKT_database)
2507 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2508 "Could not load database backend `%s'\n",
2510 GNUNET_SCHEDULER_shutdown ();
2515 GNUNET_CONFIGURATION_get_value_time (cfg,
2516 "identity-provider",
2517 "TOKEN_EXPIRATION_INTERVAL",
2518 &token_expiration_interval))
2520 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2521 "Time window for zone iteration: %s\n",
2522 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
2525 token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
2528 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2532 * Called whenever a client is disconnected.
2534 * @param cls closure
2535 * @param client identification of the client
2536 * @param app_ctx @a client
2539 client_disconnect_cb (void *cls,
2540 struct GNUNET_SERVICE_Client *client,
2543 struct IdpClient *idp = app_ctx;
2544 struct AttributeIterator *ai;
2545 struct TicketIteration *ti;
2546 struct TicketRevocationHandle *rh;
2548 //TODO other operations
2550 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2551 "Client %p disconnected\n",
2554 while (NULL != (ai = idp->op_head))
2556 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2561 while (NULL != (rh = idp->revocation_list_head))
2563 GNUNET_CONTAINER_DLL_remove (idp->revocation_list_head,
2564 idp->revocation_list_tail,
2566 cleanup_revoke_ticket_handle (rh);
2568 while (NULL != (ti = idp->ticket_iter_head))
2570 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
2571 idp->ticket_iter_tail,
2573 cleanup_ticket_iter_handle (ti);
2580 * Add a client to our list of active clients.
2583 * @param client client to add
2584 * @param mq message queue for @a client
2585 * @return internal namestore client structure for this client
2588 client_connect_cb (void *cls,
2589 struct GNUNET_SERVICE_Client *client,
2590 struct GNUNET_MQ_Handle *mq)
2592 struct IdpClient *idp;
2593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2594 "Client %p connected\n",
2596 idp = GNUNET_new (struct IdpClient);
2597 idp->client = client;
2605 * Define "main" method using service macro.
2608 ("identity-provider",
2609 GNUNET_SERVICE_OPTION_NONE,
2612 &client_disconnect_cb,
2614 GNUNET_MQ_hd_var_size (attribute_store_message,
2615 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
2616 struct AttributeStoreMessage,
2618 GNUNET_MQ_hd_fixed_size (iteration_start,
2619 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
2620 struct AttributeIterationStartMessage,
2622 GNUNET_MQ_hd_fixed_size (iteration_next,
2623 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
2624 struct AttributeIterationNextMessage,
2626 GNUNET_MQ_hd_fixed_size (iteration_stop,
2627 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
2628 struct AttributeIterationStopMessage,
2630 GNUNET_MQ_hd_var_size (issue_ticket_message,
2631 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET,
2632 struct IssueTicketMessage,
2634 GNUNET_MQ_hd_var_size (consume_ticket_message,
2635 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
2636 struct ConsumeTicketMessage,
2638 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
2639 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
2640 struct TicketIterationStartMessage,
2642 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2643 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
2644 struct TicketIterationNextMessage,
2646 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2647 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
2648 struct TicketIterationStopMessage,
2650 GNUNET_MQ_hd_var_size (revoke_ticket_message,
2651 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET,
2652 struct RevokeTicketMessage,
2654 GNUNET_MQ_handler_end());
2655 /* end of gnunet-service-identity-provider.c */