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 it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @author Martin Schanzenbach
22 * @file src/reclaim/gnunet-service-reclaim.c
23 * @brief reclaim 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_reclaim_plugin.h"
34 #include "gnunet_reclaim_attribute_lib.h"
35 #include "gnunet_signatures.h"
36 #include "gnunet-service-reclaim_tickets.h"
45 * Normal operation state
47 #define STATE_POST_INIT 1
50 * Minimum interval between updates
52 #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
55 * Standard token expiration time
57 #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
62 static struct GNUNET_IDENTITY_Handle *identity_handle;
67 static struct GNUNET_RECLAIM_PluginFunctions *TKT_database;
72 static char *db_lib_name;
75 * Token expiration interval
77 static struct GNUNET_TIME_Relative token_expiration_interval;
82 static struct GNUNET_NAMESTORE_Handle *nsh;
87 static struct GNUNET_SCHEDULER_Task *timeout_task;
92 static struct GNUNET_SCHEDULER_Task *update_task;
98 static const struct GNUNET_CONFIGURATION_Handle *cfg;
106 * A ticket iteration operation.
108 struct TicketIteration
113 struct TicketIteration *next;
118 struct TicketIteration *prev;
121 * Client which intiated this zone iteration
123 struct IdpClient *client;
126 * The operation id fot the iteration in the response for the client
131 * The ticket iterator
133 struct RECLAIM_TICKETS_Iterator *iter;
138 * An attribute iteration operation.
140 struct AttributeIterator
143 * Next element in the DLL
145 struct AttributeIterator *next;
148 * Previous element in the DLL
150 struct AttributeIterator *prev;
153 * IDP client which intiated this zone iteration
155 struct IdpClient *client;
158 * Key of the zone we are iterating over.
160 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
165 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
168 * The operation id fot the zone iteration in the response for the client
185 struct GNUNET_SERVICE_Client *client;
188 * Message queue for transmission to @e client
190 struct GNUNET_MQ_Handle *mq;
194 * Attribute iteration operations in
195 * progress initiated by this client
197 struct AttributeIterator *attr_iter_head;
201 * Attribute iteration operations
202 * in progress initiated by this client
204 struct AttributeIterator *attr_iter_tail;
207 * Head of DLL of ticket iteration ops
209 struct TicketIteration *ticket_iter_head;
212 * Tail of DLL of ticket iteration ops
214 struct TicketIteration *ticket_iter_tail;
217 * Head of DLL of ticket revocation ops
219 struct TicketRevocationHandle *revoke_op_head;
222 * Tail of DLL of ticket revocation ops
224 struct TicketRevocationHandle *revoke_op_tail;
227 * Head of DLL of ticket issue ops
229 struct TicketIssueOperation *issue_op_head;
232 * Tail of DLL of ticket issue ops
234 struct TicketIssueOperation *issue_op_tail;
237 * Head of DLL of ticket consume ops
239 struct ConsumeTicketOperation *consume_op_head;
242 * Tail of DLL of ticket consume ops
244 struct ConsumeTicketOperation *consume_op_tail;
247 * Head of DLL of attribute store ops
249 struct AttributeStoreHandle *store_op_head;
252 * Tail of DLL of attribute store ops
254 struct AttributeStoreHandle *store_op_tail;
258 struct AttributeStoreHandle
263 struct AttributeStoreHandle *next;
268 struct AttributeStoreHandle *prev;
273 struct IdpClient *client;
278 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
283 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
288 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
291 * The attribute to store
293 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
296 * The attribute expiration interval
298 struct GNUNET_TIME_Relative exp;
307 struct ConsumeTicketOperation
312 struct ConsumeTicketOperation *next;
317 struct ConsumeTicketOperation *prev;
322 struct IdpClient *client;
330 * Ticket consume handle
332 struct RECLAIM_TICKETS_ConsumeHandle *ch;
337 * Updated attribute IDs
339 struct TicketAttributeUpdateEntry
344 struct TicketAttributeUpdateEntry *next;
349 struct TicketAttributeUpdateEntry *prev;
363 * Ticket revocation request handle
365 struct TicketRevocationHandle
370 struct TicketRevocationHandle *prev;
375 struct TicketRevocationHandle *next;
380 struct TicketAttributeUpdateEntry *attr_updates_head;
385 struct TicketAttributeUpdateEntry *attr_updates_tail;
390 struct IdpClient *client;
393 * Attributes to reissue
395 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
398 * Attributes to revoke
400 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *rvk_attrs;
405 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
410 struct GNUNET_RECLAIM_Ticket ticket;
415 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
420 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
436 * Ticket issue operation handle
438 struct TicketIssueOperation
443 struct TicketIssueOperation *prev;
448 struct TicketIssueOperation *next;
453 struct IdpClient *client;
463 * DLL for ego handles to egos containing the RECLAIM_ATTRS in a
464 * map in json_t format
472 struct EgoEntry *next;
477 struct EgoEntry *prev;
482 struct GNUNET_IDENTITY_Ego *ego;
485 * Attribute map. Contains the attributes as json_t
487 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
500 RECLAIM_TICKETS_deinit ();
501 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
503 GNUNET_free (db_lib_name);
505 if (NULL != timeout_task)
506 GNUNET_SCHEDULER_cancel (timeout_task);
507 if (NULL != update_task)
508 GNUNET_SCHEDULER_cancel (update_task);
509 if (NULL != identity_handle)
510 GNUNET_IDENTITY_disconnect (identity_handle);
512 GNUNET_NAMESTORE_disconnect (nsh);
521 do_shutdown (void *cls)
523 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
524 "Shutting down...\n");
530 create_sym_key_from_ecdh (const struct GNUNET_HashCode *new_key_hash,
531 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
532 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
534 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
536 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
539 static const char ctx_key[] = "gnuid-aes-ctx-key";
540 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
541 new_key_hash, sizeof (struct GNUNET_HashCode),
542 ctx_key, strlen (ctx_key),
544 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
545 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
546 new_key_hash, sizeof (struct GNUNET_HashCode),
547 ctx_iv, strlen (ctx_iv),
554 send_ticket_result (const struct IdpClient *client,
556 const struct GNUNET_RECLAIM_Ticket *ticket,
559 struct TicketResultMessage *irm;
560 struct GNUNET_MQ_Envelope *env;
561 struct GNUNET_RECLAIM_Ticket *ticket_buf;
565 env = GNUNET_MQ_msg_extra (irm,
566 sizeof (struct GNUNET_RECLAIM_Ticket),
567 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
568 ticket_buf = (struct GNUNET_RECLAIM_Ticket *)&irm[1];
569 *ticket_buf = *ticket;
571 env = GNUNET_MQ_msg (irm,
572 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
574 //TODO add success member
575 irm->id = htonl (r_id);
576 GNUNET_MQ_send (client->mq,
582 issue_ticket_result_cb (void *cls,
583 struct GNUNET_RECLAIM_Ticket *ticket,
587 struct TicketIssueOperation *tio = cls;
588 if (GNUNET_OK != success)
590 send_ticket_result (tio->client,
594 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
595 tio->client->issue_op_tail,
598 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
599 "Error issuing ticket: %s\n",
603 send_ticket_result (tio->client,
607 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
608 tio->client->issue_op_tail,
614 check_issue_ticket_message (void *cls,
615 const struct IssueTicketMessage *im)
619 size = ntohs (im->header.size);
620 if (size <= sizeof (struct IssueTicketMessage))
623 return GNUNET_SYSERR;
629 handle_issue_ticket_message (void *cls,
630 const struct IssueTicketMessage *im)
632 struct TicketIssueOperation *tio;
633 struct IdpClient *idp = cls;
634 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
637 tio = GNUNET_new (struct TicketIssueOperation);
638 attrs_len = ntohs (im->attr_len);
639 attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char*)&im[1], attrs_len);
640 tio->r_id = ntohl (im->id);
642 GNUNET_CONTAINER_DLL_insert (idp->issue_op_head,
645 RECLAIM_TICKETS_issue (&im->identity,
648 &issue_ticket_result_cb,
650 GNUNET_SERVICE_client_continue (idp->client);
651 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
654 /**********************************************************
656 **********************************************************/
659 * Cleanup revoke handle
661 * @param rh the ticket revocation handle
664 cleanup_revoke_ticket_handle (struct TicketRevocationHandle *rh)
666 if (NULL != rh->attrs)
667 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (rh->attrs);
668 if (NULL != rh->rvk_attrs)
669 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (rh->rvk_attrs);
670 if (NULL != rh->ns_qe)
671 GNUNET_NAMESTORE_cancel (rh->ns_qe);
672 if (NULL != rh->ns_it)
673 GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
678 serialize_authz_record (const struct GNUNET_RECLAIM_Ticket *ticket,
679 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
680 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
683 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
684 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
685 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
686 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
687 struct GNUNET_HashCode new_key_hash;
695 GNUNET_assert (NULL != attrs->list_head);
697 for (le = attrs->list_head; NULL != le; le = le->next) {
698 attrs_str_len += 15 + 1; //TODO propery calculate
700 buf = GNUNET_malloc (attrs_str_len);
702 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
703 "Writing attributes\n");
704 for (le = attrs->list_head; NULL != le; le = le->next) {
705 label = GNUNET_STRINGS_data_to_string_alloc (&le->claim->id,
707 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
708 "Adding attribute to record: %s\n", label);
710 GNUNET_memcpy (write_ptr,
713 write_ptr[strlen (label)] = ',';
714 write_ptr += strlen (label) + 1;
718 write_ptr[0] = '\0'; //replace last , with a 0-terminator
719 // ECDH keypair E = eG
720 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
721 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
723 enc_keyinfo = GNUNET_malloc (attrs_str_len);
724 // Derived key K = H(eB)
725 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
728 create_sym_key_from_ecdh (&new_key_hash, &skey, &iv);
729 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
733 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
735 GNUNET_memcpy (*result,
737 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
738 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
741 GNUNET_free (enc_keyinfo);
743 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
748 * Send revocation result
750 * @param rh ticket revocation handle
751 * @param success GNUNET_OK if successful result
754 send_revocation_finished (struct TicketRevocationHandle *rh,
757 struct GNUNET_MQ_Envelope *env;
758 struct RevokeTicketResultMessage *trm;
760 GNUNET_break(TKT_database->delete_ticket (TKT_database->cls,
763 env = GNUNET_MQ_msg (trm,
764 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
765 trm->id = htonl (rh->r_id);
766 trm->success = htonl (success);
767 GNUNET_MQ_send (rh->client->mq,
769 GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head,
770 rh->client->revoke_op_tail,
776 * Process ticket from database
778 * @param cls struct TicketIterationProcResult
779 * @param ticket the ticket
780 * @param attrs the attributes
783 ticket_reissue_proc (void *cls,
784 const struct GNUNET_RECLAIM_Ticket *ticket,
785 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs);
788 revocation_reissue_tickets (struct TicketRevocationHandle *rh);
791 static void reissue_next (void *cls)
793 struct TicketRevocationHandle *rh = cls;
794 revocation_reissue_tickets (rh);
799 reissue_ticket_cont (void *cls,
803 struct TicketRevocationHandle *rh = cls;
806 if (GNUNET_SYSERR == success)
808 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
810 send_revocation_finished (rh, GNUNET_SYSERR);
811 cleanup_revoke_ticket_handle (rh);
815 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
820 * Process ticket from database
822 * @param cls struct TicketIterationProcResult
823 * @param ticket the ticket
824 * @param attrs the attributes
827 ticket_reissue_proc (void *cls,
828 const struct GNUNET_RECLAIM_Ticket *ticket,
829 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
831 struct TicketRevocationHandle *rh = cls;
832 struct TicketAttributeUpdateEntry *tue;
833 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
834 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
835 struct GNUNET_GNSRECORD_Data code_record[1];
837 size_t authz_record_len;
838 char *authz_record_data;
844 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
849 if (0 == memcmp (&ticket->audience,
850 &rh->ticket.audience,
851 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
853 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
854 "Do not reissue for this identity.!\n");
855 label = GNUNET_STRINGS_data_to_string_alloc (&rh->ticket.rnd,
858 rh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
863 &reissue_ticket_cont,
871 * Check if any attribute of this ticket intersects with a rollover attribute
873 reissue_ticket = GNUNET_NO;
874 for (le = attrs->list_head; NULL != le; le = le->next)
876 for (tue = rh->attr_updates_head;
880 if (tue->old_id == le->claim->id)
882 reissue_ticket = GNUNET_YES;
883 le->claim->id = tue->new_id;
888 if (GNUNET_NO == reissue_ticket)
890 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
891 "Skipping ticket.\n");
894 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
898 //Create new ABE key for RP
900 /* If this is the RP we want to revoke attributes of, the do so */
902 //TODO rename function
903 authz_record_len = serialize_authz_record (ticket,
907 code_record[0].data = authz_record_data;
908 code_record[0].data_size = authz_record_len;
909 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
910 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_AUTHZ;
911 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
913 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
916 rh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
921 &reissue_ticket_cont,
923 GNUNET_free (ecdhe_privkey);
925 GNUNET_free (authz_record_data);
929 /* Prototype for below function */
931 attr_reenc_cont (void *cls,
936 revocation_reissue_tickets (struct TicketRevocationHandle *rh)
939 /* Done, issue new keys */
940 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
941 "Revocation Phase III: Reissuing Tickets\n");
942 if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
943 &rh->ticket.identity,
946 &ticket_reissue_proc,
951 if (GNUNET_NO == ret)
953 send_revocation_finished (rh, GNUNET_OK);
954 cleanup_revoke_ticket_handle (rh);
960 * Failed to check for attribute
963 check_attr_error (void *cls)
965 struct TicketRevocationHandle *rh = cls;
966 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
967 "Unable to check for existing attribute\n");
969 send_revocation_finished (rh, GNUNET_SYSERR);
970 cleanup_revoke_ticket_handle (rh);
975 * Revoke next attribte by reencryption with
979 reenc_next_attribute (void *cls);
982 * Check for existing attribute and overwrite
985 check_attr_cb (void *cls,
986 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
988 unsigned int rd_count,
989 const struct GNUNET_GNSRECORD_Data *rd_old)
991 struct TicketRevocationHandle *rh = cls;
992 struct TicketAttributeUpdateEntry *tue;
993 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
994 struct GNUNET_GNSRECORD_Data rd[1];
1000 if (1 != rd_count) {
1001 le = rh->attrs->list_head;
1002 GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1003 rh->attrs->list_tail,
1005 GNUNET_assert (NULL != rh->rvk_attrs);
1006 GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
1007 rh->rvk_attrs->list_tail,
1009 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1010 "Re-encrypting next attribute\n");
1011 GNUNET_SCHEDULER_add_now (&reenc_next_attribute,
1016 buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim);
1017 buf = GNUNET_malloc (buf_size);
1018 rh->attrs->list_head->claim->version++;
1019 GNUNET_RECLAIM_ATTRIBUTE_serialize (rh->attrs->list_head->claim,
1021 tue = GNUNET_new (struct TicketAttributeUpdateEntry);
1022 tue->old_id = rh->attrs->list_head->claim->id;
1023 tue->new_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1025 GNUNET_CONTAINER_DLL_insert (rh->attr_updates_head,
1026 rh->attr_updates_tail,
1028 rh->attrs->list_head->claim->id = tue->new_id;
1029 new_label = GNUNET_STRINGS_data_to_string_alloc (&tue->new_id,
1031 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1032 "New attr id %s\n", new_label);
1033 rd[0].data_size = buf_size;
1035 rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR;
1036 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1037 rd[0].expiration_time = rd_old[0].expiration_time;
1038 rh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1049 * Revoke next attribte by reencryption with
1053 reenc_next_attribute (void *cls)
1055 struct TicketRevocationHandle *rh = cls;
1057 if (NULL == rh->attrs->list_head)
1059 revocation_reissue_tickets (rh);
1062 /* First check if attribute still exists */
1063 label = GNUNET_STRINGS_data_to_string_alloc (&rh->attrs->list_head->claim->id,
1065 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ID: %lu\n", rh->attrs->list_head->claim->id);
1066 rh->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
1073 GNUNET_free (label);
1078 * Namestore callback after revoked attribute
1082 attr_reenc_cont (void *cls,
1086 struct TicketRevocationHandle *rh = cls;
1087 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
1090 if (GNUNET_SYSERR == success)
1092 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1093 "Failed to reencrypt attribute %s\n",
1095 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1098 if (NULL == rh->attrs->list_head)
1100 revocation_reissue_tickets (rh);
1103 le = rh->attrs->list_head;
1104 GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1105 rh->attrs->list_tail,
1107 GNUNET_assert (NULL != rh->rvk_attrs);
1108 GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
1109 rh->rvk_attrs->list_tail,
1113 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1114 "Re-encrypting next attribute\n");
1115 reenc_next_attribute (rh);
1120 process_attributes_to_update (void *cls,
1121 const struct GNUNET_RECLAIM_Ticket *ticket,
1122 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
1124 struct TicketRevocationHandle *rh = cls;
1126 rh->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (attrs);
1127 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1128 "Revocation Phase I: Collecting attributes\n");
1129 /* Reencrypt all attributes with new key */
1130 if (NULL == rh->attrs->list_head)
1132 /* No attributes to reencrypt */
1133 send_revocation_finished (rh, GNUNET_OK);
1134 cleanup_revoke_ticket_handle (rh);
1137 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1138 "Revocation Phase II: Re-encrypting attributes\n");
1139 reenc_next_attribute (rh);
1146 check_revoke_ticket_message(void *cls,
1147 const struct RevokeTicketMessage *im)
1151 size = ntohs (im->header.size);
1152 if (size <= sizeof (struct RevokeTicketMessage))
1155 return GNUNET_SYSERR;
1161 handle_revoke_ticket_message (void *cls,
1162 const struct RevokeTicketMessage *rm)
1164 struct TicketRevocationHandle *rh;
1165 struct IdpClient *idp = cls;
1166 struct GNUNET_RECLAIM_Ticket *ticket;
1168 rh = GNUNET_new (struct TicketRevocationHandle);
1169 ticket = (struct GNUNET_RECLAIM_Ticket*)&rm[1];
1170 rh->rvk_attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
1171 rh->ticket = *ticket;
1172 rh->r_id = ntohl (rm->id);
1174 rh->identity = rm->identity;
1175 GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
1176 &rh->ticket.identity);
1177 GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head,
1178 idp->revoke_op_tail,
1181 * TODO replace with GNS storage
1183 TKT_database->get_ticket_attributes (TKT_database->cls,
1185 &process_attributes_to_update,
1187 GNUNET_SERVICE_client_continue (idp->client);
1192 check_consume_ticket_message (void *cls,
1193 const struct ConsumeTicketMessage *cm)
1197 size = ntohs (cm->header.size);
1198 if (size <= sizeof (struct ConsumeTicketMessage))
1201 return GNUNET_SYSERR;
1207 consume_result_cb (void *cls,
1208 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1209 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
1213 struct ConsumeTicketOperation *cop = cls;
1214 struct ConsumeTicketResultMessage *crm;
1215 struct GNUNET_MQ_Envelope *env;
1218 if (GNUNET_OK != success)
1220 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1221 "Error consuming ticket: %s\n",
1224 attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
1225 env = GNUNET_MQ_msg_extra (crm,
1227 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
1228 crm->id = htonl (cop->r_id);
1229 crm->attrs_len = htons (attrs_len);
1230 crm->identity = *identity;
1231 crm->result = htonl (success);
1232 data_tmp = (char *) &crm[1];
1233 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs,
1235 GNUNET_MQ_send (cop->client->mq, env);
1236 GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
1237 cop->client->consume_op_tail,
1244 handle_consume_ticket_message (void *cls,
1245 const struct ConsumeTicketMessage *cm)
1247 struct ConsumeTicketOperation *cop;
1248 struct GNUNET_RECLAIM_Ticket *ticket;
1249 struct IdpClient *idp = cls;
1251 cop = GNUNET_new (struct ConsumeTicketOperation);
1252 cop->r_id = ntohl (cm->id);
1254 ticket = (struct GNUNET_RECLAIM_Ticket*)&cm[1];
1255 cop->ch = RECLAIM_TICKETS_consume (&cm->identity,
1259 GNUNET_CONTAINER_DLL_insert (idp->consume_op_head,
1260 idp->consume_op_tail,
1262 GNUNET_SERVICE_client_continue (idp->client);
1265 /*****************************************
1267 *****************************************/
1270 * Cleanup attribute store handle
1272 * @param handle handle to clean up
1275 cleanup_as_handle (struct AttributeStoreHandle *ash)
1277 if (NULL != ash->ns_qe)
1278 GNUNET_NAMESTORE_cancel (ash->ns_qe);
1279 if (NULL != ash->claim)
1280 GNUNET_free (ash->claim);
1285 attr_store_cont (void *cls,
1289 struct AttributeStoreHandle *ash = cls;
1290 struct GNUNET_MQ_Envelope *env;
1291 struct AttributeStoreResultMessage *acr_msg;
1294 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1295 ash->client->store_op_tail,
1298 if (GNUNET_SYSERR == success)
1300 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1301 "Failed to store attribute %s\n",
1303 cleanup_as_handle (ash);
1304 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1308 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1309 "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1310 env = GNUNET_MQ_msg (acr_msg,
1311 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE_RESPONSE);
1312 acr_msg->id = htonl (ash->r_id);
1313 acr_msg->op_result = htonl (GNUNET_OK);
1314 GNUNET_MQ_send (ash->client->mq,
1316 cleanup_as_handle (ash);
1320 * Adds a new attribute
1322 * @param cls the AttributeStoreHandle
1325 attr_store_task (void *cls)
1327 struct AttributeStoreHandle *ash = cls;
1328 struct GNUNET_GNSRECORD_Data rd[1];
1333 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1334 "Storing attribute\n");
1335 buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (ash->claim);
1336 buf = GNUNET_malloc (buf_size);
1337 //Give the ash a new id
1338 ash->claim->id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1340 GNUNET_RECLAIM_ATTRIBUTE_serialize (ash->claim,
1342 label = GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id,
1344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1345 "Encrypting with label %s\n", label);
1347 rd[0].data_size = buf_size;
1349 rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR;
1350 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1351 rd[0].expiration_time = ash->exp.rel_value_us;
1352 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1364 check_attribute_store_message(void *cls,
1365 const struct AttributeStoreMessage *sam)
1369 size = ntohs (sam->header.size);
1370 if (size <= sizeof (struct AttributeStoreMessage))
1373 return GNUNET_SYSERR;
1380 handle_attribute_store_message (void *cls,
1381 const struct AttributeStoreMessage *sam)
1383 struct AttributeStoreHandle *ash;
1384 struct IdpClient *idp = cls;
1386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1387 "Received ATTRIBUTE_STORE message\n");
1389 data_len = ntohs (sam->attr_len);
1391 ash = GNUNET_new (struct AttributeStoreHandle);
1392 ash->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char*)&sam[1],
1395 ash->r_id = ntohl (sam->id);
1396 ash->identity = sam->identity;
1397 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1398 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1399 &ash->identity_pkey);
1401 GNUNET_SERVICE_client_continue (idp->client);
1403 GNUNET_CONTAINER_DLL_insert (idp->store_op_head,
1406 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1409 /*************************************************
1410 * Attrubute iteration
1411 *************************************************/
1414 cleanup_attribute_iter_handle (struct AttributeIterator *ai)
1420 attr_iter_error (void *cls)
1422 struct AttributeIterator *ai = cls;
1423 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1424 "Failed to iterate over attributes\n");
1425 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1426 ai->client->attr_iter_tail,
1428 cleanup_attribute_iter_handle (ai);
1429 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1433 attr_iter_finished (void *cls)
1435 struct AttributeIterator *ai = cls;
1436 struct GNUNET_MQ_Envelope *env;
1437 struct AttributeResultMessage *arm;
1439 env = GNUNET_MQ_msg (arm,
1440 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1441 arm->id = htonl (ai->request_id);
1442 arm->attr_len = htons (0);
1443 GNUNET_MQ_send (ai->client->mq, env);
1444 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1445 ai->client->attr_iter_tail,
1447 cleanup_attribute_iter_handle (ai);
1451 attr_iter_cb (void *cls,
1452 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1454 unsigned int rd_count,
1455 const struct GNUNET_GNSRECORD_Data *rd)
1457 struct AttributeIterator *ai = cls;
1458 struct AttributeResultMessage *arm;
1459 struct GNUNET_MQ_Envelope *env;
1464 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
1469 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd->record_type)
1471 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
1475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1476 "Found attribute under: %s\n", label);
1477 env = GNUNET_MQ_msg_extra (arm,
1479 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1480 arm->id = htonl (ai->request_id);
1481 arm->attr_len = htons (rd->data_size);
1482 GNUNET_CRYPTO_ecdsa_key_get_public (zone,
1484 data_tmp = (char *) &arm[1];
1485 GNUNET_memcpy (data_tmp,
1488 GNUNET_MQ_send (ai->client->mq, env);
1493 handle_iteration_start (void *cls,
1494 const struct AttributeIterationStartMessage *ais_msg)
1496 struct IdpClient *idp = cls;
1497 struct AttributeIterator *ai;
1499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1500 "Received ATTRIBUTE_ITERATION_START message\n");
1501 ai = GNUNET_new (struct AttributeIterator);
1502 ai->request_id = ntohl (ais_msg->id);
1504 ai->identity = ais_msg->identity;
1506 GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head,
1507 idp->attr_iter_tail,
1509 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1515 &attr_iter_finished,
1517 GNUNET_SERVICE_client_continue (idp->client);
1522 handle_iteration_stop (void *cls,
1523 const struct AttributeIterationStopMessage *ais_msg)
1525 struct IdpClient *idp = cls;
1526 struct AttributeIterator *ai;
1529 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1530 "Received `%s' message\n",
1531 "ATTRIBUTE_ITERATION_STOP");
1532 rid = ntohl (ais_msg->id);
1533 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1534 if (ai->request_id == rid)
1539 GNUNET_SERVICE_client_drop (idp->client);
1542 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head,
1543 idp->attr_iter_tail,
1546 GNUNET_SERVICE_client_continue (idp->client);
1551 handle_iteration_next (void *cls,
1552 const struct AttributeIterationNextMessage *ais_msg)
1554 struct IdpClient *idp = cls;
1555 struct AttributeIterator *ai;
1558 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1559 "Received ATTRIBUTE_ITERATION_NEXT message\n");
1560 rid = ntohl (ais_msg->id);
1561 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1562 if (ai->request_id == rid)
1567 GNUNET_SERVICE_client_drop (idp->client);
1570 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
1572 GNUNET_SERVICE_client_continue (idp->client);
1575 /******************************************************
1577 ******************************************************/
1580 ticket_iter_cb (void *cls,
1581 struct GNUNET_RECLAIM_Ticket *ticket)
1583 struct TicketIteration *ti = cls;
1584 struct GNUNET_MQ_Envelope *env;
1585 struct TicketResultMessage *trm;
1589 /* send empty response to indicate end of list */
1590 env = GNUNET_MQ_msg (trm,
1591 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1592 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
1593 ti->client->ticket_iter_tail,
1596 env = GNUNET_MQ_msg_extra (trm,
1597 sizeof (struct GNUNET_RECLAIM_Ticket),
1598 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1600 trm->id = htonl (ti->r_id);
1601 GNUNET_MQ_send (ti->client->mq,
1608 handle_ticket_iteration_start (void *cls,
1609 const struct TicketIterationStartMessage *tis_msg)
1611 struct IdpClient *client = cls;
1612 struct TicketIteration *ti;
1614 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1615 "Received TICKET_ITERATION_START message\n");
1616 ti = GNUNET_new (struct TicketIteration);
1617 ti->r_id = ntohl (tis_msg->id);
1618 ti->client = client;
1620 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
1621 client->ticket_iter_tail,
1623 ti->iter = RECLAIM_TICKETS_iteration_start (&tis_msg->identity,
1626 GNUNET_SERVICE_client_continue (client->client);
1631 handle_ticket_iteration_stop (void *cls,
1632 const struct TicketIterationStopMessage *tis_msg)
1634 struct IdpClient *client = cls;
1635 struct TicketIteration *ti;
1638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1639 "Received `%s' message\n",
1640 "TICKET_ITERATION_STOP");
1641 rid = ntohl (tis_msg->id);
1642 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1643 if (ti->r_id == rid)
1648 GNUNET_SERVICE_client_drop (client->client);
1651 RECLAIM_TICKETS_iteration_stop (ti->iter);
1652 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
1653 client->ticket_iter_tail,
1656 GNUNET_SERVICE_client_continue (client->client);
1661 handle_ticket_iteration_next (void *cls,
1662 const struct TicketIterationNextMessage *tis_msg)
1664 struct IdpClient *client = cls;
1665 struct TicketIteration *ti;
1668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1669 "Received TICKET_ITERATION_NEXT message\n");
1670 rid = ntohl (tis_msg->id);
1671 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1672 if (ti->r_id == rid)
1677 GNUNET_SERVICE_client_drop (client->client);
1680 RECLAIM_TICKETS_iteration_next (ti->iter);
1681 GNUNET_SERVICE_client_continue (client->client);
1688 * Main function that will be run
1690 * @param cls closure
1691 * @param c the configuration used
1692 * @param server the service handle
1696 const struct GNUNET_CONFIGURATION_Handle *c,
1697 struct GNUNET_SERVICE_Handle *server)
1703 if (GNUNET_OK != RECLAIM_TICKETS_init (cfg))
1705 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1706 "Unable to initialized TICKETS subsystem.\n");
1707 GNUNET_SCHEDULER_shutdown ();
1710 //Connect to identity and namestore services
1711 nsh = GNUNET_NAMESTORE_connect (cfg);
1714 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
1717 identity_handle = GNUNET_IDENTITY_connect (cfg,
1720 /* Loading DB plugin */
1722 GNUNET_CONFIGURATION_get_value_string (cfg,
1726 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1727 "No database backend configured\n");
1728 GNUNET_asprintf (&db_lib_name,
1729 "libgnunet_plugin_reclaim_%s",
1731 TKT_database = GNUNET_PLUGIN_load (db_lib_name,
1733 GNUNET_free (database);
1734 if (NULL == TKT_database)
1736 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1737 "Could not load database backend `%s'\n",
1739 GNUNET_SCHEDULER_shutdown ();
1744 GNUNET_CONFIGURATION_get_value_time (cfg,
1746 "TOKEN_EXPIRATION_INTERVAL",
1747 &token_expiration_interval))
1749 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1750 "Time window for zone iteration: %s\n",
1751 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
1754 token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
1757 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1761 * Called whenever a client is disconnected.
1763 * @param cls closure
1764 * @param client identification of the client
1765 * @param app_ctx @a client
1768 client_disconnect_cb (void *cls,
1769 struct GNUNET_SERVICE_Client *client,
1772 struct IdpClient *idp = app_ctx;
1773 struct AttributeIterator *ai;
1774 struct TicketIteration *ti;
1775 struct TicketRevocationHandle *rh;
1776 struct TicketIssueOperation *iss;
1777 struct ConsumeTicketOperation *ct;
1778 struct AttributeStoreHandle *as;
1780 //TODO other operations
1782 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1783 "Client %p disconnected\n",
1786 while (NULL != (iss = idp->issue_op_head))
1788 GNUNET_CONTAINER_DLL_remove (idp->issue_op_head,
1793 while (NULL != (ct = idp->consume_op_head))
1795 GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
1796 idp->consume_op_tail,
1799 RECLAIM_TICKETS_consume_cancel (ct->ch);
1802 while (NULL != (as = idp->store_op_head))
1804 GNUNET_CONTAINER_DLL_remove (idp->store_op_head,
1807 cleanup_as_handle (as);
1810 while (NULL != (ai = idp->attr_iter_head))
1812 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head,
1813 idp->attr_iter_tail,
1815 cleanup_attribute_iter_handle (ai);
1817 while (NULL != (rh = idp->revoke_op_head))
1819 GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head,
1820 idp->revoke_op_tail,
1822 cleanup_revoke_ticket_handle (rh);
1824 while (NULL != (ti = idp->ticket_iter_head))
1826 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
1827 idp->ticket_iter_tail,
1836 * Add a client to our list of active clients.
1839 * @param client client to add
1840 * @param mq message queue for @a client
1841 * @return internal namestore client structure for this client
1844 client_connect_cb (void *cls,
1845 struct GNUNET_SERVICE_Client *client,
1846 struct GNUNET_MQ_Handle *mq)
1848 struct IdpClient *idp;
1849 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1850 "Client %p connected\n",
1852 idp = GNUNET_new (struct IdpClient);
1853 idp->client = client;
1861 * Define "main" method using service macro.
1865 GNUNET_SERVICE_OPTION_NONE,
1868 &client_disconnect_cb,
1870 GNUNET_MQ_hd_var_size (attribute_store_message,
1871 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
1872 struct AttributeStoreMessage,
1874 GNUNET_MQ_hd_fixed_size (iteration_start,
1875 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
1876 struct AttributeIterationStartMessage,
1878 GNUNET_MQ_hd_fixed_size (iteration_next,
1879 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
1880 struct AttributeIterationNextMessage,
1882 GNUNET_MQ_hd_fixed_size (iteration_stop,
1883 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
1884 struct AttributeIterationStopMessage,
1886 GNUNET_MQ_hd_var_size (issue_ticket_message,
1887 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
1888 struct IssueTicketMessage,
1890 GNUNET_MQ_hd_var_size (consume_ticket_message,
1891 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
1892 struct ConsumeTicketMessage,
1894 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1895 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
1896 struct TicketIterationStartMessage,
1898 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
1899 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
1900 struct TicketIterationNextMessage,
1902 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
1903 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
1904 struct TicketIterationStopMessage,
1906 GNUNET_MQ_hd_var_size (revoke_ticket_message,
1907 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
1908 struct RevokeTicketMessage,
1910 GNUNET_MQ_handler_end());
1911 /* end of gnunet-service-reclaim.c */