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
28 #include "gnunet_util_lib.h"
30 #include "gnunet-service-reclaim_tickets.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_gnsrecord_lib.h"
33 #include "gnunet_identity_service.h"
34 #include "gnunet_namestore_service.h"
35 #include "gnunet_protocols.h"
36 #include "gnunet_reclaim_attribute_lib.h"
37 #include "gnunet_reclaim_plugin.h"
38 #include "gnunet_signatures.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_RECLAIM_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 *nsh;
89 static struct GNUNET_SCHEDULER_Task *timeout_task;
94 static struct GNUNET_SCHEDULER_Task *update_task;
99 static const struct GNUNET_CONFIGURATION_Handle *cfg;
107 * A ticket iteration operation.
109 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;
137 * An attribute iteration operation.
139 struct AttributeIterator {
141 * Next element in the DLL
143 struct AttributeIterator *next;
146 * Previous element in the DLL
148 struct AttributeIterator *prev;
151 * IDP client which intiated this zone iteration
153 struct IdpClient *client;
156 * Key of the zone we are iterating over.
158 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
163 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
166 * The operation id fot the zone iteration in the response for the client
179 struct GNUNET_SERVICE_Client *client;
182 * Message queue for transmission to @e client
184 struct GNUNET_MQ_Handle *mq;
188 * Attribute iteration operations in
189 * progress initiated by this client
191 struct AttributeIterator *attr_iter_head;
195 * Attribute iteration operations
196 * in progress initiated by this client
198 struct AttributeIterator *attr_iter_tail;
201 * Head of DLL of ticket iteration ops
203 struct TicketIteration *ticket_iter_head;
206 * Tail of DLL of ticket iteration ops
208 struct TicketIteration *ticket_iter_tail;
211 * Head of DLL of ticket revocation ops
213 struct TicketRevocationHandle *revoke_op_head;
216 * Tail of DLL of ticket revocation ops
218 struct TicketRevocationHandle *revoke_op_tail;
221 * Head of DLL of ticket issue ops
223 struct TicketIssueOperation *issue_op_head;
226 * Tail of DLL of ticket issue ops
228 struct TicketIssueOperation *issue_op_tail;
231 * Head of DLL of ticket consume ops
233 struct ConsumeTicketOperation *consume_op_head;
236 * Tail of DLL of ticket consume ops
238 struct ConsumeTicketOperation *consume_op_tail;
241 * Head of DLL of attribute store ops
243 struct AttributeStoreHandle *store_op_head;
246 * Tail of DLL of attribute store ops
248 struct AttributeStoreHandle *store_op_tail;
251 struct AttributeStoreHandle {
255 struct AttributeStoreHandle *next;
260 struct AttributeStoreHandle *prev;
265 struct IdpClient *client;
270 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
275 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
280 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
283 * The attribute to store
285 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
288 * The attribute expiration interval
290 struct GNUNET_TIME_Relative exp;
298 struct ConsumeTicketOperation {
302 struct ConsumeTicketOperation *next;
307 struct ConsumeTicketOperation *prev;
312 struct IdpClient *client;
320 * Ticket consume handle
322 struct RECLAIM_TICKETS_ConsumeHandle *ch;
326 * Updated attribute IDs
328 struct TicketAttributeUpdateEntry {
332 struct TicketAttributeUpdateEntry *next;
337 struct TicketAttributeUpdateEntry *prev;
351 * Ticket revocation request handle
353 struct TicketRevocationHandle {
357 struct TicketRevocationHandle *prev;
362 struct TicketRevocationHandle *next;
367 struct TicketAttributeUpdateEntry *attr_updates_head;
372 struct TicketAttributeUpdateEntry *attr_updates_tail;
377 struct IdpClient *client;
380 * Attributes to reissue
382 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
385 * Attributes to revoke
387 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *rvk_attrs;
392 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
397 struct GNUNET_RECLAIM_Ticket ticket;
402 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
407 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
421 * Ticket issue operation handle
423 struct TicketIssueOperation {
427 struct TicketIssueOperation *prev;
432 struct TicketIssueOperation *next;
437 struct IdpClient *client;
446 * DLL for ego handles to egos containing the RECLAIM_ATTRS in a
447 * map in json_t format
454 struct EgoEntry *next;
459 struct EgoEntry *prev;
464 struct GNUNET_IDENTITY_Ego *ego;
467 * Attribute map. Contains the attributes as json_t
469 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
475 static void cleanup ()
477 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
479 RECLAIM_TICKETS_deinit ();
480 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, TKT_database));
481 GNUNET_free (db_lib_name);
483 if (NULL != timeout_task)
484 GNUNET_SCHEDULER_cancel (timeout_task);
485 if (NULL != update_task)
486 GNUNET_SCHEDULER_cancel (update_task);
487 if (NULL != identity_handle)
488 GNUNET_IDENTITY_disconnect (identity_handle);
490 GNUNET_NAMESTORE_disconnect (nsh);
498 static void do_shutdown (void *cls)
500 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
504 static int create_sym_key_from_ecdh (
505 const struct GNUNET_HashCode *new_key_hash,
506 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
507 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
509 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
511 GNUNET_CRYPTO_hash_to_enc (new_key_hash, &new_key_hash_str);
512 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n",
513 (char *)&new_key_hash_str);
514 static const char ctx_key[] = "gnuid-aes-ctx-key";
515 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
516 new_key_hash, sizeof (struct GNUNET_HashCode), ctx_key,
517 strlen (ctx_key), NULL, 0);
518 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
520 iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
521 new_key_hash, sizeof (struct GNUNET_HashCode), ctx_iv, strlen (ctx_iv),
526 static void send_ticket_result (const struct IdpClient *client, uint32_t r_id,
527 const struct GNUNET_RECLAIM_Ticket *ticket,
530 struct TicketResultMessage *irm;
531 struct GNUNET_MQ_Envelope *env;
532 struct GNUNET_RECLAIM_Ticket *ticket_buf;
534 if (NULL != ticket) {
535 env = GNUNET_MQ_msg_extra (irm, sizeof (struct GNUNET_RECLAIM_Ticket),
536 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
537 ticket_buf = (struct GNUNET_RECLAIM_Ticket *)&irm[1];
538 *ticket_buf = *ticket;
540 env = GNUNET_MQ_msg (irm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
542 // TODO add success member
543 irm->id = htonl (r_id);
544 GNUNET_MQ_send (client->mq, env);
547 static void issue_ticket_result_cb (void *cls,
548 struct GNUNET_RECLAIM_Ticket *ticket,
549 uint32_t success, const char *emsg)
551 struct TicketIssueOperation *tio = cls;
552 if (GNUNET_OK != success) {
553 send_ticket_result (tio->client, tio->r_id, NULL, GNUNET_SYSERR);
554 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
555 tio->client->issue_op_tail, tio);
557 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
560 send_ticket_result (tio->client, tio->r_id, ticket, GNUNET_SYSERR);
561 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
562 tio->client->issue_op_tail, tio);
566 static int check_issue_ticket_message (void *cls,
567 const struct IssueTicketMessage *im)
571 size = ntohs (im->header.size);
572 if (size <= sizeof (struct IssueTicketMessage)) {
574 return GNUNET_SYSERR;
579 static void handle_issue_ticket_message (void *cls,
580 const struct IssueTicketMessage *im)
582 struct TicketIssueOperation *tio;
583 struct IdpClient *idp = cls;
584 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
587 tio = GNUNET_new (struct TicketIssueOperation);
588 attrs_len = ntohs (im->attr_len);
589 attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char *)&im[1], attrs_len);
590 tio->r_id = ntohl (im->id);
592 GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
593 RECLAIM_TICKETS_issue (&im->identity, attrs, &im->rp, &issue_ticket_result_cb,
595 GNUNET_SERVICE_client_continue (idp->client);
596 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
599 /**********************************************************
601 **********************************************************/
604 * Cleanup revoke handle
606 * @param rh the ticket revocation handle
608 static void cleanup_revoke_ticket_handle (struct TicketRevocationHandle *rh)
610 if (NULL != rh->attrs)
611 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (rh->attrs);
612 if (NULL != rh->rvk_attrs)
613 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (rh->rvk_attrs);
614 if (NULL != rh->ns_qe)
615 GNUNET_NAMESTORE_cancel (rh->ns_qe);
616 if (NULL != rh->ns_it)
617 GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
622 serialize_authz_record (const struct GNUNET_RECLAIM_Ticket *ticket,
623 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
624 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
627 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
628 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
629 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
630 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
631 struct GNUNET_HashCode new_key_hash;
639 GNUNET_assert (NULL != attrs->list_head);
641 for (le = attrs->list_head; NULL != le; le = le->next) {
642 attrs_str_len += 15 + 1; // TODO propery calculate
644 buf = GNUNET_malloc (attrs_str_len);
646 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing attributes\n");
647 for (le = attrs->list_head; NULL != le; le = le->next) {
649 GNUNET_STRINGS_data_to_string_alloc (&le->claim->id, sizeof (uint64_t));
650 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute to record: %s\n",
653 GNUNET_memcpy (write_ptr, label, strlen (label));
654 write_ptr[strlen (label)] = ',';
655 write_ptr += strlen (label) + 1;
659 write_ptr[0] = '\0'; // replace last , with a 0-terminator
660 // ECDH keypair E = eG
661 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create ();
662 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey, &ecdh_pubkey);
663 enc_keyinfo = GNUNET_malloc (attrs_str_len);
664 // Derived key K = H(eB)
665 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
668 create_sym_key_from_ecdh (&new_key_hash, &skey, &iv);
669 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf, attrs_str_len, &skey, &iv,
672 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + enc_size);
673 GNUNET_memcpy (*result, &ecdh_pubkey,
674 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
675 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
676 enc_keyinfo, enc_size);
677 GNUNET_free (enc_keyinfo);
679 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + enc_size;
683 * Send revocation result
685 * @param rh ticket revocation handle
686 * @param success GNUNET_OK if successful result
688 static void send_revocation_finished (struct TicketRevocationHandle *rh,
691 struct GNUNET_MQ_Envelope *env;
692 struct RevokeTicketResultMessage *trm;
694 GNUNET_break (TKT_database->delete_ticket (TKT_database->cls, &rh->ticket));
696 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
697 trm->id = htonl (rh->r_id);
698 trm->success = htonl (success);
699 GNUNET_MQ_send (rh->client->mq, env);
700 GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head,
701 rh->client->revoke_op_tail, rh);
705 * Process ticket from database
707 * @param cls struct TicketIterationProcResult
708 * @param ticket the ticket
709 * @param attrs the attributes
712 ticket_reissue_proc (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket,
713 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs);
715 static void revocation_reissue_tickets (struct TicketRevocationHandle *rh);
717 static void reissue_next (void *cls)
719 struct TicketRevocationHandle *rh = cls;
720 revocation_reissue_tickets (rh);
723 static void reissue_ticket_cont (void *cls, int32_t success, const char *emsg)
725 struct TicketRevocationHandle *rh = cls;
728 if (GNUNET_SYSERR == success) {
729 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", "Unknown Error\n");
730 send_revocation_finished (rh, GNUNET_SYSERR);
731 cleanup_revoke_ticket_handle (rh);
735 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
739 * Process ticket from database
741 * @param cls struct TicketIterationProcResult
742 * @param ticket the ticket
743 * @param attrs the attributes
746 ticket_reissue_proc (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket,
747 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
749 struct TicketRevocationHandle *rh = cls;
750 struct TicketAttributeUpdateEntry *tue;
751 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
752 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
753 struct GNUNET_GNSRECORD_Data code_record[1];
755 size_t authz_record_len;
756 char *authz_record_data;
759 if (NULL == ticket) {
760 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
764 if (0 == memcmp (&ticket->audience, &rh->ticket.audience,
765 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) {
766 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
767 "Do not reissue for this identity.!\n");
768 label = GNUNET_STRINGS_data_to_string_alloc (&rh->ticket.rnd,
771 rh->ns_qe = GNUNET_NAMESTORE_records_store (nsh, &rh->identity, label, 0,
772 NULL, &reissue_ticket_cont, rh);
779 * Check if any attribute of this ticket intersects with a rollover attribute
781 reissue_ticket = GNUNET_NO;
782 for (le = attrs->list_head; NULL != le; le = le->next) {
783 for (tue = rh->attr_updates_head; NULL != tue; tue = tue->next) {
784 if (tue->old_id == le->claim->id) {
785 reissue_ticket = GNUNET_YES;
786 le->claim->id = tue->new_id;
791 if (GNUNET_NO == reissue_ticket) {
792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping ticket.\n");
795 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
799 // Create new ABE key for RP
801 /* If this is the RP we want to revoke attributes of, the do so */
803 // TODO rename function
804 authz_record_len = serialize_authz_record (ticket, attrs, &ecdhe_privkey,
806 code_record[0].data = authz_record_data;
807 code_record[0].data_size = authz_record_len;
808 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
809 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF;
810 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
812 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof (uint64_t));
814 rh->ns_qe = GNUNET_NAMESTORE_records_store (
815 nsh, &rh->identity, label, 1, code_record, &reissue_ticket_cont, rh);
816 GNUNET_free (ecdhe_privkey);
818 GNUNET_free (authz_record_data);
821 /* Prototype for below function */
822 static void attr_reenc_cont (void *cls, int32_t success, const char *emsg);
824 static void revocation_reissue_tickets (struct TicketRevocationHandle *rh)
827 /* Done, issue new keys */
828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
829 "Revocation Phase III: Reissuing Tickets\n");
830 if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (
831 TKT_database->cls, &rh->ticket.identity, GNUNET_NO,
832 rh->offset, &ticket_reissue_proc, rh))) {
835 if (GNUNET_NO == ret) {
836 send_revocation_finished (rh, GNUNET_OK);
837 cleanup_revoke_ticket_handle (rh);
843 * Failed to check for attribute
845 static void check_attr_error (void *cls)
847 struct TicketRevocationHandle *rh = cls;
848 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
849 "Unable to check for existing attribute\n");
851 send_revocation_finished (rh, GNUNET_SYSERR);
852 cleanup_revoke_ticket_handle (rh);
856 * Revoke next attribte by reencryption with
859 static void reenc_next_attribute (void *cls);
862 * Check for existing attribute and overwrite
864 static void check_attr_cb (void *cls,
865 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
866 const char *label, unsigned int rd_count,
867 const struct GNUNET_GNSRECORD_Data *rd_old)
869 struct TicketRevocationHandle *rh = cls;
870 struct TicketAttributeUpdateEntry *tue;
871 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
872 struct GNUNET_GNSRECORD_Data rd[1];
879 le = rh->attrs->list_head;
880 GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head, rh->attrs->list_tail,
882 GNUNET_assert (NULL != rh->rvk_attrs);
883 GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
884 rh->rvk_attrs->list_tail, le);
885 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Re-encrypting next attribute\n");
886 GNUNET_SCHEDULER_add_now (&reenc_next_attribute, rh);
891 GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim);
892 buf = GNUNET_malloc (buf_size);
893 rh->attrs->list_head->claim->version++;
894 GNUNET_RECLAIM_ATTRIBUTE_serialize (rh->attrs->list_head->claim, buf);
895 tue = GNUNET_new (struct TicketAttributeUpdateEntry);
896 tue->old_id = rh->attrs->list_head->claim->id;
898 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
899 GNUNET_CONTAINER_DLL_insert (rh->attr_updates_head, rh->attr_updates_tail,
901 rh->attrs->list_head->claim->id = tue->new_id;
903 GNUNET_STRINGS_data_to_string_alloc (&tue->new_id, sizeof (uint64_t));
904 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "New attr id %s\n", new_label);
905 rd[0].data_size = buf_size;
907 rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR;
908 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
909 rd[0].expiration_time = rd_old[0].expiration_time;
910 rh->ns_qe = GNUNET_NAMESTORE_records_store (nsh, &rh->identity, new_label, 1,
911 rd, &attr_reenc_cont, rh);
915 * Revoke next attribte by reencryption with
918 static void reenc_next_attribute (void *cls)
920 struct TicketRevocationHandle *rh = cls;
922 if (NULL == rh->attrs->list_head) {
923 revocation_reissue_tickets (rh);
926 /* First check if attribute still exists */
927 label = GNUNET_STRINGS_data_to_string_alloc (&rh->attrs->list_head->claim->id,
929 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Name: %s\n",
930 rh->attrs->list_head->claim->name);
931 rh->ns_qe = GNUNET_NAMESTORE_records_lookup (
932 nsh, &rh->identity, label, &check_attr_error, rh, &check_attr_cb, rh);
937 * Namestore callback after revoked attribute
940 static void attr_reenc_cont (void *cls, int32_t success, const char *emsg)
942 struct TicketRevocationHandle *rh = cls;
943 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
946 if (GNUNET_SYSERR == success) {
947 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to reencrypt attribute %s\n",
949 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
952 if (NULL == rh->attrs->list_head) {
953 revocation_reissue_tickets (rh);
956 le = rh->attrs->list_head;
957 GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head, rh->attrs->list_tail, le);
958 GNUNET_assert (NULL != rh->rvk_attrs);
959 GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
960 rh->rvk_attrs->list_tail, le);
962 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Re-encrypting next attribute\n");
963 reenc_next_attribute (rh);
967 static void process_attributes_to_update (
968 void *cls, const struct GNUNET_RECLAIM_Ticket *ticket,
969 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
971 struct TicketRevocationHandle *rh = cls;
973 rh->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (attrs);
974 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
975 "Revocation Phase I: Collecting attributes\n");
976 /* Reencrypt all attributes with new key */
977 if (NULL == rh->attrs->list_head) {
978 /* No attributes to reencrypt */
979 send_revocation_finished (rh, GNUNET_OK);
980 cleanup_revoke_ticket_handle (rh);
983 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
984 "Revocation Phase II: Re-encrypting attributes\n");
985 reenc_next_attribute (rh);
989 static int check_revoke_ticket_message (void *cls,
990 const struct RevokeTicketMessage *im)
994 size = ntohs (im->header.size);
995 if (size <= sizeof (struct RevokeTicketMessage)) {
997 return GNUNET_SYSERR;
1002 static void handle_revoke_ticket_message (void *cls,
1003 const struct RevokeTicketMessage *rm)
1005 struct TicketRevocationHandle *rh;
1006 struct IdpClient *idp = cls;
1007 struct GNUNET_RECLAIM_Ticket *ticket;
1009 rh = GNUNET_new (struct TicketRevocationHandle);
1010 ticket = (struct GNUNET_RECLAIM_Ticket *)&rm[1];
1011 rh->rvk_attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
1012 rh->ticket = *ticket;
1013 rh->r_id = ntohl (rm->id);
1015 rh->identity = rm->identity;
1016 GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity, &rh->ticket.identity);
1017 GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, idp->revoke_op_tail, rh);
1019 * TODO replace with GNS storage
1021 TKT_database->get_ticket_attributes (TKT_database->cls, &rh->ticket,
1022 &process_attributes_to_update, rh);
1023 GNUNET_SERVICE_client_continue (idp->client);
1026 static int check_consume_ticket_message (void *cls,
1027 const struct ConsumeTicketMessage *cm)
1031 size = ntohs (cm->header.size);
1032 if (size <= sizeof (struct ConsumeTicketMessage)) {
1034 return GNUNET_SYSERR;
1040 consume_result_cb (void *cls,
1041 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1042 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
1043 uint32_t success, const char *emsg)
1045 struct ConsumeTicketOperation *cop = cls;
1046 struct ConsumeTicketResultMessage *crm;
1047 struct GNUNET_MQ_Envelope *env;
1050 if (GNUNET_OK != success) {
1051 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
1053 attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
1054 env = GNUNET_MQ_msg_extra (crm, attrs_len,
1055 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
1056 crm->id = htonl (cop->r_id);
1057 crm->attrs_len = htons (attrs_len);
1058 crm->identity = *identity;
1059 crm->result = htonl (success);
1060 data_tmp = (char *)&crm[1];
1061 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, data_tmp);
1062 GNUNET_MQ_send (cop->client->mq, env);
1063 GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
1064 cop->client->consume_op_tail, cop);
1069 handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
1071 struct ConsumeTicketOperation *cop;
1072 struct GNUNET_RECLAIM_Ticket *ticket;
1073 struct IdpClient *idp = cls;
1075 cop = GNUNET_new (struct ConsumeTicketOperation);
1076 cop->r_id = ntohl (cm->id);
1078 ticket = (struct GNUNET_RECLAIM_Ticket *)&cm[1];
1080 RECLAIM_TICKETS_consume (&cm->identity, ticket, &consume_result_cb, cop);
1081 GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, idp->consume_op_tail, cop);
1082 GNUNET_SERVICE_client_continue (idp->client);
1085 /*****************************************
1087 *****************************************/
1090 * Cleanup attribute store handle
1092 * @param handle handle to clean up
1094 static void cleanup_as_handle (struct AttributeStoreHandle *ash)
1096 if (NULL != ash->ns_qe)
1097 GNUNET_NAMESTORE_cancel (ash->ns_qe);
1098 if (NULL != ash->claim)
1099 GNUNET_free (ash->claim);
1103 static void attr_store_cont (void *cls, int32_t success, const char *emsg)
1105 struct AttributeStoreHandle *ash = cls;
1106 struct GNUNET_MQ_Envelope *env;
1107 struct AttributeStoreResultMessage *acr_msg;
1110 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1111 ash->client->store_op_tail, ash);
1113 if (GNUNET_SYSERR == success) {
1114 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to store attribute %s\n",
1116 cleanup_as_handle (ash);
1117 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1121 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1122 "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1123 env = GNUNET_MQ_msg (acr_msg,
1124 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE_RESPONSE);
1125 acr_msg->id = htonl (ash->r_id);
1126 acr_msg->op_result = htonl (GNUNET_OK);
1127 GNUNET_MQ_send (ash->client->mq, env);
1128 cleanup_as_handle (ash);
1132 * Adds a new attribute
1134 * @param cls the AttributeStoreHandle
1136 static void attr_store_task (void *cls)
1138 struct AttributeStoreHandle *ash = cls;
1139 struct GNUNET_GNSRECORD_Data rd[1];
1144 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attribute\n");
1145 buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (ash->claim);
1146 buf = GNUNET_malloc (buf_size);
1147 // Give the ash a new id
1149 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
1150 GNUNET_RECLAIM_ATTRIBUTE_serialize (ash->claim, buf);
1152 GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id, sizeof (uint64_t));
1153 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1155 rd[0].data_size = buf_size;
1157 rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR;
1158 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1159 rd[0].expiration_time = ash->exp.rel_value_us;
1160 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh, &ash->identity, label, 1,
1161 rd, &attr_store_cont, ash);
1166 check_attribute_store_message (void *cls,
1167 const struct AttributeStoreMessage *sam)
1171 size = ntohs (sam->header.size);
1172 if (size <= sizeof (struct AttributeStoreMessage)) {
1174 return GNUNET_SYSERR;
1180 handle_attribute_store_message (void *cls,
1181 const struct AttributeStoreMessage *sam)
1183 struct AttributeStoreHandle *ash;
1184 struct IdpClient *idp = cls;
1186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_STORE message\n");
1188 data_len = ntohs (sam->attr_len);
1190 ash = GNUNET_new (struct AttributeStoreHandle);
1191 ash->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *)&sam[1], data_len);
1193 ash->r_id = ntohl (sam->id);
1194 ash->identity = sam->identity;
1195 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1196 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
1198 GNUNET_SERVICE_client_continue (idp->client);
1200 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1201 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1204 /*************************************************
1205 * Attrubute iteration
1206 *************************************************/
1208 static void cleanup_attribute_iter_handle (struct AttributeIterator *ai)
1213 static void attr_iter_error (void *cls)
1215 struct AttributeIterator *ai = cls;
1216 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
1217 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1218 ai->client->attr_iter_tail, ai);
1219 cleanup_attribute_iter_handle (ai);
1220 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1223 static void attr_iter_finished (void *cls)
1225 struct AttributeIterator *ai = cls;
1226 struct GNUNET_MQ_Envelope *env;
1227 struct AttributeResultMessage *arm;
1229 env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1230 arm->id = htonl (ai->request_id);
1231 arm->attr_len = htons (0);
1232 GNUNET_MQ_send (ai->client->mq, env);
1233 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1234 ai->client->attr_iter_tail, ai);
1235 cleanup_attribute_iter_handle (ai);
1238 static void attr_iter_cb (void *cls,
1239 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1240 const char *label, unsigned int rd_count,
1241 const struct GNUNET_GNSRECORD_Data *rd)
1243 struct AttributeIterator *ai = cls;
1244 struct AttributeResultMessage *arm;
1245 struct GNUNET_MQ_Envelope *env;
1248 if (rd_count != 1) {
1249 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1253 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd->record_type) {
1254 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1257 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n", label);
1258 env = GNUNET_MQ_msg_extra (arm, rd->data_size,
1259 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1260 arm->id = htonl (ai->request_id);
1261 arm->attr_len = htons (rd->data_size);
1262 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
1263 data_tmp = (char *)&arm[1];
1264 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1265 GNUNET_MQ_send (ai->client->mq, env);
1269 handle_iteration_start (void *cls,
1270 const struct AttributeIterationStartMessage *ais_msg)
1272 struct IdpClient *idp = cls;
1273 struct AttributeIterator *ai;
1275 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1276 "Received ATTRIBUTE_ITERATION_START message\n");
1277 ai = GNUNET_new (struct AttributeIterator);
1278 ai->request_id = ntohl (ais_msg->id);
1280 ai->identity = ais_msg->identity;
1282 GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
1283 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (
1284 nsh, &ai->identity, &attr_iter_error, ai, &attr_iter_cb, ai,
1285 &attr_iter_finished, ai);
1286 GNUNET_SERVICE_client_continue (idp->client);
1290 handle_iteration_stop (void *cls,
1291 const struct AttributeIterationStopMessage *ais_msg)
1293 struct IdpClient *idp = cls;
1294 struct AttributeIterator *ai;
1297 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n",
1298 "ATTRIBUTE_ITERATION_STOP");
1299 rid = ntohl (ais_msg->id);
1300 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1301 if (ai->request_id == rid)
1305 GNUNET_SERVICE_client_drop (idp->client);
1308 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1310 GNUNET_SERVICE_client_continue (idp->client);
1314 handle_iteration_next (void *cls,
1315 const struct AttributeIterationNextMessage *ais_msg)
1317 struct IdpClient *idp = cls;
1318 struct AttributeIterator *ai;
1321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1322 "Received ATTRIBUTE_ITERATION_NEXT message\n");
1323 rid = ntohl (ais_msg->id);
1324 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1325 if (ai->request_id == rid)
1329 GNUNET_SERVICE_client_drop (idp->client);
1332 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1333 GNUNET_SERVICE_client_continue (idp->client);
1336 /******************************************************
1338 ******************************************************/
1340 static void ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket)
1342 struct TicketIteration *ti = cls;
1343 struct GNUNET_MQ_Envelope *env;
1344 struct TicketResultMessage *trm;
1346 if (NULL == ticket) {
1347 /* send empty response to indicate end of list */
1348 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1349 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
1350 ti->client->ticket_iter_tail, ti);
1352 env = GNUNET_MQ_msg_extra (trm, sizeof (struct GNUNET_RECLAIM_Ticket),
1353 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1355 trm->id = htonl (ti->r_id);
1356 GNUNET_MQ_send (ti->client->mq, env);
1361 static void handle_ticket_iteration_start (
1362 void *cls, const struct TicketIterationStartMessage *tis_msg)
1364 struct IdpClient *client = cls;
1365 struct TicketIteration *ti;
1367 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1368 "Received TICKET_ITERATION_START message\n");
1369 ti = GNUNET_new (struct TicketIteration);
1370 ti->r_id = ntohl (tis_msg->id);
1371 ti->client = client;
1373 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
1374 client->ticket_iter_tail, ti);
1376 RECLAIM_TICKETS_iteration_start (&tis_msg->identity, &ticket_iter_cb, ti);
1377 GNUNET_SERVICE_client_continue (client->client);
1381 handle_ticket_iteration_stop (void *cls,
1382 const struct TicketIterationStopMessage *tis_msg)
1384 struct IdpClient *client = cls;
1385 struct TicketIteration *ti;
1388 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n",
1389 "TICKET_ITERATION_STOP");
1390 rid = ntohl (tis_msg->id);
1391 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1392 if (ti->r_id == rid)
1396 GNUNET_SERVICE_client_drop (client->client);
1399 RECLAIM_TICKETS_iteration_stop (ti->iter);
1400 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
1401 client->ticket_iter_tail, ti);
1403 GNUNET_SERVICE_client_continue (client->client);
1407 handle_ticket_iteration_next (void *cls,
1408 const struct TicketIterationNextMessage *tis_msg)
1410 struct IdpClient *client = cls;
1411 struct TicketIteration *ti;
1414 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1415 "Received TICKET_ITERATION_NEXT message\n");
1416 rid = ntohl (tis_msg->id);
1417 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1418 if (ti->r_id == rid)
1422 GNUNET_SERVICE_client_drop (client->client);
1425 RECLAIM_TICKETS_iteration_next (ti->iter);
1426 GNUNET_SERVICE_client_continue (client->client);
1430 * Main function that will be run
1432 * @param cls closure
1433 * @param c the configuration used
1434 * @param server the service handle
1436 static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c,
1437 struct GNUNET_SERVICE_Handle *server)
1442 if (GNUNET_OK != RECLAIM_TICKETS_init (cfg)) {
1443 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1444 "Unable to initialized TICKETS subsystem.\n");
1445 GNUNET_SCHEDULER_shutdown ();
1448 // Connect to identity and namestore services
1449 nsh = GNUNET_NAMESTORE_connect (cfg);
1451 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1452 "error connecting to namestore");
1455 identity_handle = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
1456 /* Loading DB plugin */
1457 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (
1458 cfg, "reclaim", "database", &database))
1459 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
1460 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_reclaim_%s", database);
1461 TKT_database = GNUNET_PLUGIN_load (db_lib_name, (void *)cfg);
1462 GNUNET_free (database);
1463 if (NULL == TKT_database) {
1464 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1465 "Could not load database backend `%s'\n", db_lib_name);
1466 GNUNET_SCHEDULER_shutdown ();
1470 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (
1471 cfg, "reclaim", "TOKEN_EXPIRATION_INTERVAL",
1472 &token_expiration_interval)) {
1473 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Time window for zone iteration: %s\n",
1474 GNUNET_STRINGS_relative_time_to_string (
1475 token_expiration_interval, GNUNET_YES));
1477 token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
1480 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1484 * Called whenever a client is disconnected.
1486 * @param cls closure
1487 * @param client identification of the client
1488 * @param app_ctx @a client
1490 static void client_disconnect_cb (void *cls,
1491 struct GNUNET_SERVICE_Client *client,
1494 struct IdpClient *idp = app_ctx;
1495 struct AttributeIterator *ai;
1496 struct TicketIteration *ti;
1497 struct TicketRevocationHandle *rh;
1498 struct TicketIssueOperation *iss;
1499 struct ConsumeTicketOperation *ct;
1500 struct AttributeStoreHandle *as;
1502 // TODO other operations
1504 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1506 while (NULL != (iss = idp->issue_op_head)) {
1507 GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, idp->issue_op_tail, iss);
1510 while (NULL != (ct = idp->consume_op_head)) {
1511 GNUNET_CONTAINER_DLL_remove (idp->consume_op_head, idp->consume_op_tail,
1514 RECLAIM_TICKETS_consume_cancel (ct->ch);
1517 while (NULL != (as = idp->store_op_head)) {
1518 GNUNET_CONTAINER_DLL_remove (idp->store_op_head, idp->store_op_tail, as);
1519 cleanup_as_handle (as);
1522 while (NULL != (ai = idp->attr_iter_head)) {
1523 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1524 cleanup_attribute_iter_handle (ai);
1526 while (NULL != (rh = idp->revoke_op_head)) {
1527 GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, idp->revoke_op_tail, rh);
1528 cleanup_revoke_ticket_handle (rh);
1530 while (NULL != (ti = idp->ticket_iter_head)) {
1531 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head, idp->ticket_iter_tail,
1539 * Add a client to our list of active clients.
1542 * @param client client to add
1543 * @param mq message queue for @a client
1544 * @return internal namestore client structure for this client
1546 static void *client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *client,
1547 struct GNUNET_MQ_Handle *mq)
1549 struct IdpClient *idp;
1550 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1551 idp = GNUNET_new (struct IdpClient);
1552 idp->client = client;
1558 * Define "main" method using service macro.
1560 GNUNET_SERVICE_MAIN (
1561 "reclaim", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb,
1562 &client_disconnect_cb, NULL,
1563 GNUNET_MQ_hd_var_size (attribute_store_message,
1564 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
1565 struct AttributeStoreMessage, NULL),
1566 GNUNET_MQ_hd_fixed_size (
1567 iteration_start, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
1568 struct AttributeIterationStartMessage, NULL),
1569 GNUNET_MQ_hd_fixed_size (
1570 iteration_next, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
1571 struct AttributeIterationNextMessage, NULL),
1572 GNUNET_MQ_hd_fixed_size (
1573 iteration_stop, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
1574 struct AttributeIterationStopMessage, NULL),
1575 GNUNET_MQ_hd_var_size (issue_ticket_message,
1576 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
1577 struct IssueTicketMessage, NULL),
1578 GNUNET_MQ_hd_var_size (consume_ticket_message,
1579 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
1580 struct ConsumeTicketMessage, NULL),
1581 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1582 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
1583 struct TicketIterationStartMessage, NULL),
1584 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
1585 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
1586 struct TicketIterationNextMessage, NULL),
1587 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
1588 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
1589 struct TicketIterationStopMessage, NULL),
1590 GNUNET_MQ_hd_var_size (revoke_ticket_message,
1591 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
1592 struct RevokeTicketMessage, NULL),
1593 GNUNET_MQ_handler_end ());
1594 /* end of gnunet-service-reclaim.c */