RECLAIM: forgot conf file for tests
[oweals/gnunet.git] / src / reclaim / gnunet-service-reclaim.c
1 /*
2    This file is part of GNUnet.
3    Copyright (C) 2012-2015 GNUnet e.V.
4
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.
9
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.
14   
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/>.
17    */
18 /**
19  * @author Martin Schanzenbach
20  * @file src/reclaim/gnunet-service-reclaim.c
21  * @brief reclaim Service
22  *
23  */
24 #include "platform.h"
25 #include "gnunet_util_lib.h"
26 #include "gnunet_constants.h"
27 #include "gnunet_protocols.h"
28 #include "gnunet_identity_service.h"
29 #include "gnunet_gnsrecord_lib.h"
30 #include "gnunet_namestore_service.h"
31 #include "gnunet_abe_lib.h"
32 #include "gnunet_credential_service.h"
33 #include "gnunet_statistics_service.h"
34 #include "gnunet_gns_service.h"
35 #include "gnunet_reclaim_plugin.h"
36 #include "gnunet_reclaim_attribute_lib.h"
37 #include "gnunet_signatures.h"
38 #include "reclaim.h"
39
40 /**
41  * First pass state
42  */
43 #define STATE_INIT 0
44
45 /**
46  * Normal operation state
47  */
48 #define STATE_POST_INIT 1
49
50 /**
51  * Minimum interval between updates
52  */
53 #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
54
55 /**
56  * Standard token expiration time
57  */
58 #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
59
60 /**
61  * Identity handle
62  */
63 static struct GNUNET_IDENTITY_Handle *identity_handle;
64
65 /**
66  * Database handle
67  */
68 static struct GNUNET_RECLAIM_PluginFunctions *TKT_database;
69
70 /**
71  * Name of DB plugin
72  */
73 static char *db_lib_name;
74
75 /**
76  * Token expiration interval
77  */
78 static struct GNUNET_TIME_Relative token_expiration_interval;
79
80 /**
81  * Namestore handle
82  */
83 static struct GNUNET_NAMESTORE_Handle *ns_handle;
84
85 /**
86  * GNS handle
87  */
88 static struct GNUNET_GNS_Handle *gns_handle;
89
90 /**
91  * Credential handle
92  */
93 static struct GNUNET_CREDENTIAL_Handle *credential_handle;
94
95 /**
96  * Namestore qe
97  */
98 static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
99
100 /**
101  * Namestore iterator
102  */
103 static struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
104
105 /**
106  * Timeout task
107  */
108 static struct GNUNET_SCHEDULER_Task *timeout_task;
109
110 /**
111  * Update task
112  */
113 static struct GNUNET_SCHEDULER_Task *update_task;
114
115
116 /**
117  * Currently processed token
118  */
119 static struct IdentityToken *token;
120
121 /**
122  * Label for currently processed token
123  */
124 static char* label;
125
126 /**
127  * Scopes for processed token
128  */
129 static char* scopes;
130
131 /**
132  * Handle to the statistics service.
133  */
134 static struct GNUNET_STATISTICS_Handle *stats;
135
136 /**
137  * Our configuration.
138  */
139 static const struct GNUNET_CONFIGURATION_Handle *cfg;
140
141 /**
142  * An idp client
143  */
144 struct IdpClient;
145
146 /**
147  * A ticket iteration operation.
148  */
149 struct TicketIteration
150 {
151   /**
152    * DLL
153    */
154   struct TicketIteration *next;
155
156   /**
157    * DLL
158    */
159   struct TicketIteration *prev;
160
161   /**
162    * Client which intiated this zone iteration
163    */
164   struct IdpClient *client;
165
166   /**
167    * Key of the identity we are iterating over.
168    */
169   struct GNUNET_CRYPTO_EcdsaPublicKey identity;
170
171   /**
172    * Identity is audience
173    */
174   uint32_t is_audience;
175
176   /**
177    * The operation id fot the iteration in the response for the client
178    */
179   uint32_t r_id;
180
181   /**
182    * Offset of the iteration used to address next result of the 
183    * iteration in the store
184    *
185    * Initialy set to 0 in handle_iteration_start
186    * Incremented with by every call to handle_iteration_next
187    */
188   uint32_t offset;
189
190 };
191
192
193
194 /**
195  * Callback after an ABE bootstrap
196  *
197  * @param cls closure
198  * @param abe_key the ABE key that exists or was created
199  */
200 typedef void
201 (*AbeBootstrapResult) (void *cls,
202                        struct GNUNET_ABE_AbeMasterKey *abe_key);
203
204
205 struct AbeBootstrapHandle
206 {
207   /**
208    * Function to call when finished
209    */
210   AbeBootstrapResult proc;
211
212   /**
213    * Callback closure
214    */
215   char *proc_cls;
216
217   /**
218    * Key of the zone we are iterating over.
219    */
220   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
221
222   /**
223    * Namestore Queue Entry
224    */
225   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
226
227   /**
228    * The issuer egos ABE master key
229    */
230   struct GNUNET_ABE_AbeMasterKey *abe_key;
231 };
232
233 /**
234  * An attribute iteration operation.
235  */
236 struct AttributeIterator
237 {
238   /**
239    * Next element in the DLL
240    */
241   struct AttributeIterator *next;
242
243   /**
244    * Previous element in the DLL
245    */
246   struct AttributeIterator *prev;
247
248   /**
249    * IDP client which intiated this zone iteration
250    */
251   struct IdpClient *client;
252
253   /**
254    * Key of the zone we are iterating over.
255    */
256   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
257
258   /**
259    * The issuer egos ABE master key
260    */
261   struct GNUNET_ABE_AbeMasterKey *abe_key;
262
263   /**
264    * Namestore iterator
265    */
266   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
267
268   /**
269    * The operation id fot the zone iteration in the response for the client
270    */
271   uint32_t request_id;
272
273 };
274
275
276
277 /**
278  * An idp client
279  */
280 struct IdpClient
281 {
282
283   /**
284    * The client
285    */
286   struct GNUNET_SERVICE_Client *client;
287
288   /**
289    * Message queue for transmission to @e client
290    */
291   struct GNUNET_MQ_Handle *mq;
292   
293   /**
294    * Head of the DLL of
295    * Attribute iteration operations in 
296    * progress initiated by this client
297    */
298   struct AttributeIterator *attr_iter_head;
299
300   /**
301    * Tail of the DLL of
302    * Attribute iteration operations 
303    * in progress initiated by this client
304    */
305   struct AttributeIterator *attr_iter_tail;
306
307   /**
308    * Head of DLL of ticket iteration ops
309    */
310   struct TicketIteration *ticket_iter_head;
311
312   /**
313    * Tail of DLL of ticket iteration ops
314    */
315   struct TicketIteration *ticket_iter_tail;
316
317   /**
318    * Head of DLL of ticket revocation ops
319    */
320   struct TicketRevocationHandle *revoke_op_head;
321
322   /**
323    * Tail of DLL of ticket revocation ops
324    */
325   struct TicketRevocationHandle *revoke_op_tail;
326
327   /**
328    * Head of DLL of ticket issue ops
329    */
330   struct TicketIssueHandle *issue_op_head;
331
332   /**
333    * Tail of DLL of ticket issue ops
334    */
335   struct TicketIssueHandle *issue_op_tail;
336
337   /**
338    * Head of DLL of ticket consume ops
339    */
340   struct ConsumeTicketHandle *consume_op_head;
341
342   /**
343    * Tail of DLL of ticket consume ops
344    */
345   struct ConsumeTicketHandle *consume_op_tail;
346
347   /**
348    * Head of DLL of attribute store ops
349    */
350   struct AttributeStoreHandle *store_op_head;
351
352   /**
353    * Tail of DLL of attribute store ops
354    */
355   struct AttributeStoreHandle *store_op_tail;
356
357 };
358
359 struct AttributeStoreHandle
360 {
361   /**
362    * DLL
363    */
364   struct AttributeStoreHandle *next;
365
366   /**
367    * DLL
368    */
369   struct AttributeStoreHandle *prev;
370
371   /**
372    * Client connection
373    */
374   struct IdpClient *client;
375
376   /**
377    * Identity
378    */
379   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
380
381   /**
382    * Identity pubkey
383    */
384   struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
385
386   /**
387    * The issuer egos ABE master key
388    */
389   struct GNUNET_ABE_AbeMasterKey *abe_key;
390
391   /**
392    * QueueEntry
393    */
394   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
395
396   /**
397    * The attribute to store
398    */
399   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
400
401   /**
402    * The attribute expiration interval
403    */
404   struct GNUNET_TIME_Relative exp;
405
406   /**
407    * request id
408    */
409   uint32_t r_id;
410 };
411
412
413 /* Prototype */
414 struct ParallelLookup;
415
416 struct ConsumeTicketHandle
417 {
418   /**
419    * DLL
420    */
421   struct ConsumeTicketHandle *next;
422
423   /**
424    * DLL
425    */
426   struct ConsumeTicketHandle *prev;
427
428   /**
429    * Client connection
430    */
431   struct IdpClient *client;
432
433   /**
434    * Ticket
435    */
436   struct GNUNET_RECLAIM_Ticket ticket;
437
438   /**
439    * LookupRequest
440    */
441   struct GNUNET_GNS_LookupRequest *lookup_request;
442
443   /**
444    * Audience Key
445    */
446   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
447
448   /**
449    * Audience Key
450    */
451   struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
452
453   /**
454    * Lookup DLL
455    */
456   struct ParallelLookup *parallel_lookups_head;
457
458   /**
459    * Lookup DLL
460    */
461   struct ParallelLookup *parallel_lookups_tail;
462   
463   /**
464    * Kill task
465    */
466   struct GNUNET_SCHEDULER_Task *kill_task;
467
468   /**
469    * The ABE key
470    */
471   struct GNUNET_ABE_AbeKey *key;
472
473   /**
474    * Attributes
475    */
476   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
477   
478   /**
479    * Lookup time
480    */
481   struct GNUNET_TIME_Absolute lookup_start_time;
482  
483   /**
484    * request id
485    */
486   uint32_t r_id;
487 };
488
489 /**
490  * Handle for a parallel GNS lookup job
491  */
492 struct ParallelLookup
493 {
494   /* DLL */
495   struct ParallelLookup *next;
496
497   /* DLL */
498   struct ParallelLookup *prev;
499
500   /* The GNS request */
501   struct GNUNET_GNS_LookupRequest *lookup_request;
502
503   /* The handle the return to */
504   struct ConsumeTicketHandle *handle;
505
506   /**
507    * Lookup time
508    */
509   struct GNUNET_TIME_Absolute lookup_start_time;
510
511   /* The label to look up */
512   char *label;
513 };
514
515 /**
516  * Ticket revocation request handle
517  */
518 struct TicketRevocationHandle
519 {
520   /**
521    * DLL
522    */
523   struct TicketRevocationHandle *prev;
524
525   /**
526    * DLL
527    */
528   struct TicketRevocationHandle *next;
529
530   /**
531    * Client connection
532    */
533   struct IdpClient *client;
534
535   /**
536    * Attributes to reissue
537    */
538   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
539
540   /**
541    * Attributes to revoke
542    */
543   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *rvk_attrs;
544
545   /**
546    * Issuer Key
547    */
548   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
549
550   /**
551    * Ticket to issue
552    */
553   struct GNUNET_RECLAIM_Ticket ticket;
554
555   /**
556    * QueueEntry
557    */
558   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
559
560   /**
561    * Namestore iterator
562    */
563   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
564
565   /**
566    * The ABE master key
567    */
568   struct GNUNET_ABE_AbeMasterKey *abe_key;
569
570   /**
571    * Offset
572    */
573   uint32_t offset;
574
575   /**
576    * request id
577    */
578   uint32_t r_id;
579 };
580
581
582
583 /**
584  * Ticket issue request handle
585  */
586 struct TicketIssueHandle
587 {
588   /**
589    * DLL
590    */
591   struct TicketIssueHandle *prev;
592
593   /**
594    * DLL
595    */
596   struct TicketIssueHandle *next;
597
598   /**
599    * Client connection
600    */
601   struct IdpClient *client;
602
603   /**
604    * Attributes to issue
605    */
606   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
607
608   /**
609    * Issuer Key
610    */
611   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
612
613   /**
614    * Ticket to issue
615    */
616   struct GNUNET_RECLAIM_Ticket ticket;
617
618   /**
619    * QueueEntry
620    */
621   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
622
623   /**
624    * request id
625    */
626   uint32_t r_id;
627 };
628
629
630 /**
631  * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
632  *
633  */
634 struct EgoEntry
635 {
636   /**
637    * DLL
638    */
639   struct EgoEntry *next;
640
641   /**
642    * DLL
643    */
644   struct EgoEntry *prev;
645
646   /**
647    * Ego handle
648    */
649   struct GNUNET_IDENTITY_Ego *ego;
650
651   /**
652    * Attribute map. Contains the attributes as json_t
653    */
654   struct GNUNET_CONTAINER_MultiHashMap *attr_map;
655
656 };
657
658 /**
659  * Cleanup task
660  */
661 static void
662 cleanup()
663 {
664   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
665               "Cleaning up\n");
666
667   if (NULL != stats)
668   {
669     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
670     stats = NULL;
671   }
672   GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
673                                               TKT_database)); 
674   GNUNET_free (db_lib_name);
675   db_lib_name = NULL;
676   if (NULL != timeout_task)
677     GNUNET_SCHEDULER_cancel (timeout_task);
678   if (NULL != update_task)
679     GNUNET_SCHEDULER_cancel (update_task);
680   if (NULL != identity_handle)
681     GNUNET_IDENTITY_disconnect (identity_handle);
682   if (NULL != gns_handle)
683     GNUNET_GNS_disconnect (gns_handle);
684   if (NULL != credential_handle)
685     GNUNET_CREDENTIAL_disconnect (credential_handle);
686   if (NULL != ns_it)
687     GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
688   if (NULL != ns_qe)
689     GNUNET_NAMESTORE_cancel (ns_qe);
690   if (NULL != ns_handle)
691     GNUNET_NAMESTORE_disconnect (ns_handle);
692   GNUNET_free_non_null (token);
693   GNUNET_free_non_null (label);
694
695 }
696
697 /**
698  * Shutdown task
699  *
700  * @param cls NULL
701  */
702 static void
703 do_shutdown (void *cls)
704 {
705   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
706               "Shutting down...\n");
707   cleanup();
708 }
709
710 /**
711  * Finished storing newly bootstrapped ABE key
712  */
713 static void
714 bootstrap_store_cont (void *cls,
715                       int32_t success,
716                       const char *emsg)
717 {
718   struct AbeBootstrapHandle *abh = cls;
719   if (GNUNET_SYSERR == success)
720   {
721     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
722                 "Failed to bootstrap ABE master %s\n",
723                 emsg);
724     abh->proc (abh->proc_cls, NULL);
725     GNUNET_free (abh->abe_key);
726     GNUNET_free (abh);
727     return;
728   }
729   abh->proc (abh->proc_cls, abh->abe_key);
730   GNUNET_free (abh);
731 }
732
733 /**
734  * Generates and stores a new ABE key
735  */
736 static void
737 bootstrap_store_task (void *cls)
738 {
739   struct AbeBootstrapHandle *abh = cls;
740   struct GNUNET_GNSRECORD_Data rd[1];
741   char *key;
742
743   rd[0].data_size = GNUNET_ABE_cpabe_serialize_master_key (abh->abe_key,
744                                                               (void**)&key);
745   rd[0].data = key;
746   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
747   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
748   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
749   abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
750                                                &abh->identity,
751                                                "+",
752                                                1,
753                                                rd,
754                                                &bootstrap_store_cont,
755                                                abh);
756   GNUNET_free (key);
757 }
758
759 /**
760  * Error checking for ABE master
761  */
762 static void
763 bootstrap_abe_error (void *cls)
764 {
765   struct AbeBootstrapHandle *abh = cls;
766   abh->proc (abh->proc_cls, NULL);
767   GNUNET_free (abh);
768 }
769
770
771 /**
772  * Handle ABE lookup in namestore
773  */
774 static void
775 bootstrap_abe_result (void *cls,
776                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
777                       const char *label,
778                       unsigned int rd_count,
779                       const struct GNUNET_GNSRECORD_Data *rd)
780 {
781   struct AbeBootstrapHandle *abh = cls;
782   struct GNUNET_ABE_AbeMasterKey *abe_key;
783
784   for (uint32_t i=0;i<rd_count;i++) {
785     if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
786       continue;
787     abe_key = GNUNET_ABE_cpabe_deserialize_master_key (rd[i].data,
788                                                           rd[i].data_size);
789     abh->proc (abh->proc_cls, abe_key);
790     GNUNET_free (abh);
791     return;
792   }
793
794   //No ABE master found, bootstrapping...
795   abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
796   GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
797 }
798
799 /**
800  * Bootstrap ABE master if it does not yet exists.
801  * Will call the AbeBootstrapResult processor when done.
802  * will always recreate the ABE key of GNUNET_YES == recreate
803  */
804 static void
805 bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
806                AbeBootstrapResult proc,
807                void* cls,
808                int recreate)
809 {
810   struct AbeBootstrapHandle *abh;
811
812   abh = GNUNET_new (struct AbeBootstrapHandle);
813   abh->proc = proc;
814   abh->proc_cls = cls;
815   abh->identity = *identity;
816   if (GNUNET_YES == recreate)
817   {
818     abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
819     GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
820   } else {
821     abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
822                                                   identity,
823                                                   "+",
824                                                   &bootstrap_abe_error,
825                                                   abh,
826                                                   &bootstrap_abe_result,
827                                                   abh);
828   }
829 }
830
831
832
833 static int
834 create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
835                          struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
836                          struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
837 {
838   struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
839
840   GNUNET_CRYPTO_hash_to_enc (new_key_hash,
841                              &new_key_hash_str);
842   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
843   static const char ctx_key[] = "gnuid-aes-ctx-key";
844   GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
845                      new_key_hash, sizeof (struct GNUNET_HashCode),
846                      ctx_key, strlen (ctx_key),
847                      NULL, 0);
848   static const char ctx_iv[] = "gnuid-aes-ctx-iv";
849   GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
850                      new_key_hash, sizeof (struct GNUNET_HashCode),
851                      ctx_iv, strlen (ctx_iv),
852                      NULL, 0);
853   return GNUNET_OK;
854 }
855
856 /**
857  * Cleanup ticket consume handle
858  * @param handle the handle to clean up
859  */
860 static void
861 cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
862 {
863   if (NULL != handle->attrs)
864     GNUNET_RECLAIM_ATTRIBUTE_list_destroy (handle->attrs);
865   if (NULL != handle->ns_qe)
866     GNUNET_NAMESTORE_cancel (handle->ns_qe);
867   GNUNET_free (handle);
868 }
869
870
871 static void
872 send_ticket_result (struct IdpClient *client,
873                     uint32_t r_id,
874                     const struct GNUNET_RECLAIM_Ticket *ticket,
875                     const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
876 {
877   struct TicketResultMessage *irm;
878   struct GNUNET_MQ_Envelope *env;
879   struct GNUNET_RECLAIM_Ticket *ticket_buf;
880
881   /* store ticket in DB */
882   if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
883                                                ticket,
884                                                attrs))
885   {
886     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
887                 "Unable to store ticket after issue\n");
888     GNUNET_break (0);
889   }
890
891   env = GNUNET_MQ_msg_extra (irm,
892                              sizeof (struct GNUNET_RECLAIM_Ticket),
893                              GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
894   ticket_buf = (struct GNUNET_RECLAIM_Ticket *)&irm[1];
895   *ticket_buf = *ticket;
896   irm->id = htonl (r_id);
897   GNUNET_MQ_send (client->mq,
898                   env);
899 }
900
901 static void
902 store_ticket_issue_cont (void *cls,
903                          int32_t success,
904                          const char *emsg)
905 {
906   struct TicketIssueHandle *handle = cls;
907
908   handle->ns_qe = NULL;
909   GNUNET_CONTAINER_DLL_remove (handle->client->issue_op_head,
910                                handle->client->issue_op_tail,
911                                handle);
912   if (GNUNET_SYSERR == success)
913   {
914     cleanup_ticket_issue_handle (handle);
915     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
916                 "Unknown Error\n");
917     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
918     return;
919   }
920   send_ticket_result (handle->client,
921                       handle->r_id,
922                       &handle->ticket,
923                       handle->attrs);
924   cleanup_ticket_issue_handle (handle);
925 }
926
927
928
929 int
930 serialize_abe_keyinfo2 (const struct GNUNET_RECLAIM_Ticket *ticket,
931                         const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
932                         const struct GNUNET_ABE_AbeKey *rp_key,
933                         struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
934                         char **result)
935 {
936   struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
937   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
938   char *enc_keyinfo;
939   char *serialized_key;
940   char *buf;
941   char *write_ptr;
942   char attrs_str_len;
943   ssize_t size;
944
945   struct GNUNET_CRYPTO_SymmetricSessionKey skey;
946   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
947   struct GNUNET_HashCode new_key_hash;
948   ssize_t enc_size;
949
950   size = GNUNET_ABE_cpabe_serialize_key (rp_key,
951                                          (void**)&serialized_key);
952   attrs_str_len = 0;
953   for (le = attrs->list_head; NULL != le; le = le->next) {
954     attrs_str_len += strlen (le->claim->name) + 1;
955   }
956   buf = GNUNET_malloc (attrs_str_len + size);
957   write_ptr = buf;
958   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
959               "Writing attributes\n");
960   for (le = attrs->list_head; NULL != le; le = le->next) {
961     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
962                 "%s\n", le->claim->name);
963
964
965     GNUNET_memcpy (write_ptr,
966                    le->claim->name,
967                    strlen (le->claim->name));
968     write_ptr[strlen (le->claim->name)] = ',';
969     write_ptr += strlen (le->claim->name) + 1;
970   }
971   write_ptr--;
972   write_ptr[0] = '\0'; //replace last , with a 0-terminator
973   write_ptr++;
974   GNUNET_memcpy (write_ptr,
975                  serialized_key,
976                  size);
977   GNUNET_free (serialized_key);
978   // ECDH keypair E = eG
979   *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
980   GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
981                                       &ecdh_pubkey);
982   enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
983   // Derived key K = H(eB)
984   GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
985                                                         &ticket->audience,
986                                                         &new_key_hash));
987   create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
988   enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
989                                               size + attrs_str_len,
990                                               &skey, &iv,
991                                               enc_keyinfo);
992   *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
993                            enc_size);
994   GNUNET_memcpy (*result,
995                  &ecdh_pubkey,
996                  sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
997   GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
998                  enc_keyinfo,
999                  enc_size);
1000   GNUNET_free (enc_keyinfo);
1001   GNUNET_free (buf);
1002   return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
1003 }
1004
1005
1006
1007 static void
1008 issue_ticket_after_abe_bootstrap (void *cls,
1009                                   struct GNUNET_ABE_AbeMasterKey *abe_key)
1010 {
1011   struct TicketIssueHandle *ih = cls;
1012   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
1013   struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
1014   struct GNUNET_GNSRECORD_Data code_record[1];
1015   struct GNUNET_ABE_AbeKey *rp_key;
1016   char *code_record_data;
1017   char **attrs;
1018   char *label;
1019   char *policy;
1020   int attrs_len;
1021   uint32_t i;
1022   size_t code_record_len;
1023
1024   //Create new ABE key for RP
1025   attrs_len = 0;
1026   for (le = ih->attrs->list_head; NULL != le; le = le->next)
1027     attrs_len++;
1028   attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1029   i = 0;
1030   for (le = ih->attrs->list_head; NULL != le; le = le->next) {
1031     GNUNET_asprintf (&policy, "%s_%lu",
1032                      le->claim->name,
1033                      le->claim->version);
1034     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1035                 "Adding attribute to key: %s\n",
1036                 policy);
1037     attrs[i] = policy;
1038     i++;
1039   }
1040   attrs[i] = NULL;
1041   rp_key = GNUNET_ABE_cpabe_create_key (abe_key,
1042                                         attrs);
1043
1044   //TODO review this wireformat
1045   code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
1046                                             ih->attrs,
1047                                             rp_key,
1048                                             &ecdhe_privkey,
1049                                             &code_record_data);
1050   code_record[0].data = code_record_data;
1051   code_record[0].data_size = code_record_len;
1052   code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1053   code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1054   code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1055
1056   label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
1057                                                sizeof (uint64_t));
1058   //Publish record
1059   ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1060                                               &ih->identity,
1061                                               label,
1062                                               1,
1063                                               code_record,
1064                                               &store_ticket_issue_cont,
1065                                               ih);
1066   //for (; i > 0; i--)
1067   //  GNUNET_free (attrs[i-1]);
1068   GNUNET_free (ecdhe_privkey);
1069   GNUNET_free (label);
1070   GNUNET_free (attrs);
1071   GNUNET_free (code_record_data);
1072   GNUNET_ABE_cpabe_delete_key (rp_key,
1073                                GNUNET_YES);
1074   GNUNET_ABE_cpabe_delete_master_key (abe_key);
1075 }
1076
1077
1078 static int
1079 check_issue_ticket_message(void *cls,
1080                            const struct IssueTicketMessage *im)
1081 {
1082   uint16_t size;
1083
1084   size = ntohs (im->header.size);
1085   if (size <= sizeof (struct IssueTicketMessage))
1086   {
1087     GNUNET_break (0);
1088     return GNUNET_SYSERR;
1089   }
1090   return GNUNET_OK;
1091 }
1092
1093
1094 static void
1095 handle_issue_ticket_message (void *cls,
1096                              const struct IssueTicketMessage *im)
1097 {
1098   struct TicketIssueHandle *ih;
1099   struct IdpClient *idp = cls;
1100   size_t attrs_len;
1101
1102   ih = GNUNET_new (struct TicketIssueHandle);
1103   attrs_len = ntohs (im->attr_len);
1104   ih->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char*)&im[1], attrs_len);
1105   ih->r_id = ntohl (im->id);
1106   ih->client = idp;
1107   ih->identity = im->identity;
1108   GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
1109                                       &ih->ticket.identity);
1110   ih->ticket.audience = im->rp;
1111   ih->ticket.rnd =
1112     GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1113                               UINT64_MAX);
1114   GNUNET_CONTAINER_DLL_insert (idp->issue_op_head,
1115                                idp->issue_op_tail,
1116                                ih);
1117   bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
1118   GNUNET_SERVICE_client_continue (idp->client);
1119
1120 }
1121
1122 /**********************************************************
1123  * Revocation
1124  **********************************************************/
1125
1126 /**
1127  * Cleanup revoke handle
1128  *
1129  * @param rh the ticket revocation handle
1130  */
1131 static void
1132 cleanup_revoke_ticket_handle (struct TicketRevocationHandle *rh)
1133 {
1134   if (NULL != rh->attrs)
1135     GNUNET_RECLAIM_ATTRIBUTE_list_destroy (rh->attrs);
1136   if (NULL != rh->rvk_attrs)
1137     GNUNET_RECLAIM_ATTRIBUTE_list_destroy (rh->rvk_attrs);
1138   if (NULL != rh->abe_key)
1139     GNUNET_ABE_cpabe_delete_master_key (rh->abe_key);
1140   if (NULL != rh->ns_qe)
1141     GNUNET_NAMESTORE_cancel (rh->ns_qe);
1142   if (NULL != rh->ns_it)
1143     GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
1144   GNUNET_free (rh);
1145 }
1146
1147
1148 /**
1149  * Send revocation result
1150  *
1151  * @param rh ticket revocation handle
1152  * @param success GNUNET_OK if successful result
1153  */
1154 static void
1155 send_revocation_finished (struct TicketRevocationHandle *rh,
1156                           uint32_t success)
1157 {
1158   struct GNUNET_MQ_Envelope *env;
1159   struct RevokeTicketResultMessage *trm;
1160   
1161   GNUNET_break(TKT_database->delete_ticket (TKT_database->cls,
1162                                             &rh->ticket));
1163
1164   env = GNUNET_MQ_msg (trm,
1165                        GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
1166   trm->id = htonl (rh->r_id);
1167   trm->success = htonl (success);
1168   GNUNET_MQ_send (rh->client->mq,
1169                   env);
1170   GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head,
1171                                rh->client->revoke_op_tail,
1172                                rh);
1173 }
1174
1175
1176 /**
1177  * Process ticket from database
1178  *
1179  * @param cls struct TicketIterationProcResult
1180  * @param ticket the ticket
1181  * @param attrs the attributes
1182  */
1183 static void
1184 ticket_reissue_proc (void *cls,
1185                      const struct GNUNET_RECLAIM_Ticket *ticket,
1186                      const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs);
1187
1188 static void
1189 revocation_reissue_tickets (struct TicketRevocationHandle *rh);
1190
1191
1192 static void reissue_next (void *cls)
1193 {
1194   struct TicketRevocationHandle *rh = cls;
1195   revocation_reissue_tickets (rh);
1196 }
1197
1198
1199 static void
1200 reissue_ticket_cont (void *cls,
1201                      int32_t success,
1202                      const char *emsg)
1203 {
1204   struct TicketRevocationHandle *rh = cls;
1205
1206   rh->ns_qe = NULL;
1207   if (GNUNET_SYSERR == success)
1208   {
1209     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1210                 "Unknown Error\n");
1211     send_revocation_finished (rh, GNUNET_SYSERR);
1212     cleanup_revoke_ticket_handle (rh);
1213     return;
1214   }
1215   rh->offset++;
1216   GNUNET_SCHEDULER_add_now (&reissue_next, rh);
1217 }
1218
1219
1220 /**
1221  * Process ticket from database
1222  *
1223  * @param cls struct TicketIterationProcResult
1224  * @param ticket the ticket
1225  * @param attrs the attributes
1226  */
1227 static void
1228 ticket_reissue_proc (void *cls,
1229                      const struct GNUNET_RECLAIM_Ticket *ticket,
1230                      const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
1231 {
1232   struct TicketRevocationHandle *rh = cls;
1233   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
1234   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le_rollover;
1235   struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
1236   struct GNUNET_GNSRECORD_Data code_record[1];
1237   struct GNUNET_ABE_AbeKey *rp_key;
1238   char *code_record_data;
1239   char **attr_arr;
1240   char *label;
1241   char *policy;
1242   int attrs_len;
1243   uint32_t i;
1244   int reissue_ticket;
1245   size_t code_record_len;
1246
1247
1248   if (NULL == ticket)
1249   {
1250     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1251                 "Iteration done\n");
1252     return;
1253   }
1254
1255   if (0 == memcmp (&ticket->audience,
1256                    &rh->ticket.audience,
1257                    sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
1258   {
1259     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1260                 "Do not reissue for this identity.!\n");
1261     label = GNUNET_STRINGS_data_to_string_alloc (&rh->ticket.rnd,
1262                                                  sizeof (uint64_t));
1263     //Delete record
1264     rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1265                                                 &rh->identity,
1266                                                 label,
1267                                                 0,
1268                                                 NULL,
1269                                                 &reissue_ticket_cont,
1270                                                 rh);
1271
1272     GNUNET_free (label);
1273     return;
1274   }
1275
1276   /* 
1277    * Check if any attribute of this ticket intersects with a rollover attribute
1278    */
1279   reissue_ticket = GNUNET_NO;
1280   for (le = attrs->list_head; NULL != le; le = le->next)
1281   {
1282     for (le_rollover = rh->rvk_attrs->list_head;
1283          NULL != le_rollover;
1284          le_rollover = le_rollover->next)
1285     {
1286       if (0 == strcmp (le_rollover->claim->name,
1287                        le->claim->name))
1288       {
1289         reissue_ticket = GNUNET_YES;
1290         le->claim->version = le_rollover->claim->version;
1291       }
1292     }
1293   }
1294
1295   if (GNUNET_NO == reissue_ticket)
1296   {
1297     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1298                 "Skipping ticket.\n");
1299
1300     rh->offset++;
1301     GNUNET_SCHEDULER_add_now (&reissue_next, rh);
1302
1303
1304     return;
1305   }
1306
1307   //Create new ABE key for RP
1308   attrs_len = 0;
1309
1310   /* If this is the RP we want to revoke attributes of, the do so */
1311
1312   for (le = attrs->list_head; NULL != le; le = le->next)
1313     attrs_len++;
1314   attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1315   i = 0;
1316   for (le = attrs->list_head; NULL != le; le = le->next) {
1317     GNUNET_asprintf (&policy, "%s_%lu",
1318                      le->claim->name,
1319                      le->claim->version);
1320     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1321                 "Recreating key with %s\n", policy);
1322     attr_arr[i] = policy;
1323     i++;
1324   }
1325   attr_arr[i] = NULL;
1326   rp_key = GNUNET_ABE_cpabe_create_key (rh->abe_key,
1327                                         attr_arr);
1328
1329   //TODO review this wireformat
1330   code_record_len = serialize_abe_keyinfo2 (ticket,
1331                                             attrs,
1332                                             rp_key,
1333                                             &ecdhe_privkey,
1334                                             &code_record_data);
1335   code_record[0].data = code_record_data;
1336   code_record[0].data_size = code_record_len;
1337   code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1338   code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1339   code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1340
1341   label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
1342                                                sizeof (uint64_t));
1343   //Publish record
1344   rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1345                                               &rh->identity,
1346                                               label,
1347                                               1,
1348                                               code_record,
1349                                               &reissue_ticket_cont,
1350                                               rh);
1351   //for (; i > 0; i--)
1352   //  GNUNET_free (attr_arr[i-1]);
1353   GNUNET_free (ecdhe_privkey);
1354   GNUNET_free (label);
1355   GNUNET_free (attr_arr);
1356   GNUNET_free (code_record_data);
1357   GNUNET_ABE_cpabe_delete_key (rp_key, GNUNET_YES);
1358 }
1359
1360
1361 /* Prototype for below function */
1362 static void
1363 attr_reenc_cont (void *cls,
1364                  int32_t success,
1365                  const char *emsg);
1366
1367 static void
1368 revocation_reissue_tickets (struct TicketRevocationHandle *rh)
1369 {
1370   int ret;
1371   /* Done, issue new keys */
1372   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1373               "Revocation Phase III: Reissuing Tickets\n");
1374   if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
1375                                                              &rh->ticket.identity,
1376                                                              GNUNET_NO,
1377                                                              rh->offset,
1378                                                              &ticket_reissue_proc,
1379                                                              rh)))
1380   {
1381     GNUNET_break (0);
1382   }
1383   if (GNUNET_NO == ret)
1384   {
1385     send_revocation_finished (rh, GNUNET_OK);
1386     cleanup_revoke_ticket_handle (rh);
1387     return;
1388   }
1389 }
1390
1391 /**
1392  * Failed to check for attribute
1393  */
1394 static void
1395 check_attr_error (void *cls)
1396 {
1397   struct TicketRevocationHandle *rh = cls;
1398   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1399               "Unable to check for existing attribute\n");
1400   rh->ns_qe = NULL;
1401   send_revocation_finished (rh, GNUNET_SYSERR);
1402   cleanup_revoke_ticket_handle (rh);
1403 }
1404
1405
1406 /**
1407  * Revoke next attribte by reencryption with
1408  * new ABE master
1409  */
1410 static void
1411 reenc_next_attribute (void *cls);
1412
1413 /**
1414  * Check for existing attribute and overwrite
1415  */
1416 static void
1417 check_attr_cb (void *cls,
1418                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1419                const char *label,
1420                unsigned int rd_count,
1421                const struct GNUNET_GNSRECORD_Data *rd_old)
1422 {
1423   struct TicketRevocationHandle *rh = cls;
1424   struct GNUNET_GNSRECORD_Data rd[1];
1425   char* buf;
1426   char* enc_buf;
1427   size_t enc_size;
1428   char* rd_buf;
1429   size_t buf_size;
1430   char* policy;
1431   uint32_t attr_ver;
1432
1433   rh->ns_qe = NULL;
1434   if (1 != rd_count) {
1435     GNUNET_SCHEDULER_add_now (&reenc_next_attribute,
1436                               rh);
1437     return;
1438   }
1439
1440   buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim);
1441   buf = GNUNET_malloc (buf_size);
1442   rh->attrs->list_head->claim->version++;
1443   GNUNET_RECLAIM_ATTRIBUTE_serialize (rh->attrs->list_head->claim,
1444                                        buf);
1445   GNUNET_asprintf (&policy, "%s_%lu",
1446                    rh->attrs->list_head->claim->name,
1447                    rh->attrs->list_head->claim->version);
1448   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1449               "Encrypting with policy %s\n", policy);
1450   /**
1451    * Encrypt the attribute value and store in namestore
1452    */
1453   enc_size = GNUNET_ABE_cpabe_encrypt (buf,
1454                                        buf_size,
1455                                        policy, //Policy
1456                                        rh->abe_key,
1457                                        (void**)&enc_buf);
1458   GNUNET_free (buf);
1459   if (GNUNET_SYSERR == enc_size)
1460   {
1461     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1462                 "Unable to re-encrypt with policy %s\n",
1463                 policy);
1464     GNUNET_free (policy);
1465     send_revocation_finished (rh, GNUNET_SYSERR);
1466     cleanup_revoke_ticket_handle (rh);
1467     return;
1468   }
1469   GNUNET_free (policy);
1470
1471   rd[0].data_size = enc_size + sizeof (uint32_t);
1472   rd_buf = GNUNET_malloc (rd[0].data_size);
1473   attr_ver = htonl (rh->attrs->list_head->claim->version);
1474   GNUNET_memcpy (rd_buf,
1475                  &attr_ver,
1476                  sizeof (uint32_t));
1477   GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1478                  enc_buf,
1479                  enc_size);
1480   rd[0].data = rd_buf;
1481   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1482   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1483   rd[0].expiration_time = rd_old[0].expiration_time;
1484   rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1485                                               &rh->identity,
1486                                               rh->attrs->list_head->claim->name,
1487                                               1,
1488                                               rd,
1489                                               &attr_reenc_cont,
1490                                               rh);
1491   GNUNET_free (enc_buf);
1492   GNUNET_free (rd_buf);
1493 }
1494
1495
1496 /**
1497  * Revoke next attribte by reencryption with
1498  * new ABE master
1499  */
1500 static void
1501 reenc_next_attribute (void *cls)
1502 {
1503   struct TicketRevocationHandle *rh = cls;
1504   if (NULL == rh->attrs->list_head)
1505   {
1506     revocation_reissue_tickets (rh);
1507     return;
1508   }
1509   /* First check if attribute still exists */
1510   rh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
1511                                                &rh->identity,
1512                                                rh->attrs->list_head->claim->name,
1513                                                &check_attr_error,
1514                                                rh,
1515                                                &check_attr_cb,
1516                                                rh);
1517 }
1518
1519
1520 /**
1521  * Namestore callback after revoked attribute
1522  * is stored
1523  */
1524 static void
1525 attr_reenc_cont (void *cls,
1526                  int32_t success,
1527                  const char *emsg)
1528 {
1529   struct TicketRevocationHandle *rh = cls;
1530   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
1531
1532   rh->ns_qe = NULL;
1533   if (GNUNET_SYSERR == success)
1534   {
1535     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1536                 "Failed to reencrypt attribute %s\n",
1537                 emsg);
1538     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1539     return;
1540   }
1541   if (NULL == rh->attrs->list_head)
1542   {
1543     revocation_reissue_tickets (rh);
1544     return;
1545   }
1546   le = rh->attrs->list_head;
1547   GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1548                                rh->attrs->list_tail,
1549                                le);
1550   GNUNET_assert (NULL != rh->rvk_attrs);
1551   GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
1552                                rh->rvk_attrs->list_tail,
1553                                le);
1554
1555
1556   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1557               "Re-encrypting next attribute\n");
1558   reenc_next_attribute (rh);
1559 }
1560
1561
1562 static void
1563 process_attributes_to_update (void *cls,
1564                               const struct GNUNET_RECLAIM_Ticket *ticket,
1565                               const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
1566 {
1567   struct TicketRevocationHandle *rh = cls;
1568
1569   rh->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (attrs);
1570   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1571               "Revocation Phase I: Collecting attributes\n");
1572   /* Reencrypt all attributes with new key */
1573   if (NULL == rh->attrs->list_head)
1574   {
1575     /* No attributes to reencrypt */
1576     send_revocation_finished (rh, GNUNET_OK);
1577     cleanup_revoke_ticket_handle (rh);
1578     return;
1579   } else {
1580     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1581                 "Revocation Phase II: Re-encrypting attributes\n");
1582     reenc_next_attribute (rh);
1583   }
1584
1585 }
1586
1587
1588
1589 static void
1590 get_ticket_after_abe_bootstrap (void *cls,
1591                                 struct GNUNET_ABE_AbeMasterKey *abe_key)
1592 {
1593   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1594               "Finished ABE bootstrap\n");
1595   struct TicketRevocationHandle *rh = cls;
1596   rh->abe_key = abe_key;
1597   TKT_database->get_ticket_attributes (TKT_database->cls,
1598                                        &rh->ticket,
1599                                        &process_attributes_to_update,
1600                                        rh);
1601 }
1602
1603 static int
1604 check_revoke_ticket_message(void *cls,
1605                             const struct RevokeTicketMessage *im)
1606 {
1607   uint16_t size;
1608
1609   size = ntohs (im->header.size);
1610   if (size <= sizeof (struct RevokeTicketMessage))
1611   {
1612     GNUNET_break (0);
1613     return GNUNET_SYSERR;
1614   }
1615   return GNUNET_OK;
1616 }
1617
1618 static void
1619 handle_revoke_ticket_message (void *cls,
1620                               const struct RevokeTicketMessage *rm)
1621 {
1622   struct TicketRevocationHandle *rh;
1623   struct IdpClient *idp = cls;
1624   struct GNUNET_RECLAIM_Ticket *ticket;
1625
1626   rh = GNUNET_new (struct TicketRevocationHandle);
1627   ticket = (struct GNUNET_RECLAIM_Ticket*)&rm[1];
1628   rh->rvk_attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
1629   rh->ticket = *ticket;
1630   rh->r_id = ntohl (rm->id);
1631   rh->client = idp;
1632   rh->identity = rm->identity;
1633   GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
1634                                       &rh->ticket.identity);
1635   GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head,
1636                                idp->revoke_op_tail,
1637                                rh);
1638   bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO);
1639   GNUNET_SERVICE_client_continue (idp->client);
1640
1641 }
1642
1643 /**
1644  * Cleanup ticket consume handle
1645  * @param handle the handle to clean up
1646  */
1647 static void
1648 cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
1649 {
1650   struct ParallelLookup *lu;  
1651   struct ParallelLookup *tmp;
1652   if (NULL != handle->lookup_request)
1653     GNUNET_GNS_lookup_cancel (handle->lookup_request);
1654   for (lu = handle->parallel_lookups_head;
1655        NULL != lu;) {
1656     GNUNET_GNS_lookup_cancel (lu->lookup_request);
1657     GNUNET_free (lu->label);
1658     tmp = lu->next;
1659     GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1660                                  handle->parallel_lookups_tail,
1661                                  lu);
1662     GNUNET_free (lu);
1663     lu = tmp;
1664   }
1665
1666   if (NULL != handle->key)
1667     GNUNET_ABE_cpabe_delete_key (handle->key,
1668                                  GNUNET_YES);
1669   if (NULL != handle->attrs)
1670     GNUNET_RECLAIM_ATTRIBUTE_list_destroy (handle->attrs);
1671   GNUNET_free (handle);
1672 }
1673
1674
1675
1676 static int
1677 check_consume_ticket_message(void *cls,
1678                              const struct ConsumeTicketMessage *cm)
1679 {
1680   uint16_t size;
1681
1682   size = ntohs (cm->header.size);
1683   if (size <= sizeof (struct ConsumeTicketMessage))
1684   {
1685     GNUNET_break (0);
1686     return GNUNET_SYSERR;
1687   }
1688   return GNUNET_OK;
1689 }
1690
1691 static void
1692 process_parallel_lookup2 (void *cls, uint32_t rd_count,
1693                           const struct GNUNET_GNSRECORD_Data *rd)
1694 {
1695   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1696               "Parallel lookup finished (count=%u)\n", rd_count);
1697   struct ParallelLookup *parallel_lookup = cls;
1698   struct ConsumeTicketHandle *handle = parallel_lookup->handle;
1699   struct ConsumeTicketResultMessage *crm;
1700   struct GNUNET_MQ_Envelope *env;
1701   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *attr_le;
1702   struct GNUNET_TIME_Absolute decrypt_duration;
1703   char *data;
1704   char *data_tmp;
1705   ssize_t attr_len;
1706   size_t attrs_len;
1707
1708   GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1709                                handle->parallel_lookups_tail,
1710                                parallel_lookup);
1711   GNUNET_free (parallel_lookup->label);
1712
1713   GNUNET_STATISTICS_update (stats,
1714                             "attribute_lookup_time_total",
1715                             GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us,
1716                             GNUNET_YES);
1717   GNUNET_STATISTICS_update (stats,
1718                             "attribute_lookups_count",
1719                             1,
1720                             GNUNET_YES);
1721
1722
1723   GNUNET_free (parallel_lookup);
1724   if (1 != rd_count)
1725     GNUNET_break(0);//TODO
1726   if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1727   {
1728     decrypt_duration = GNUNET_TIME_absolute_get ();
1729     attr_len = GNUNET_ABE_cpabe_decrypt (rd->data + sizeof (uint32_t),
1730                                          rd->data_size - sizeof (uint32_t),
1731                                          handle->key,
1732                                          (void**)&data);
1733     if (GNUNET_SYSERR != attr_len) 
1734     {
1735       GNUNET_STATISTICS_update (stats,
1736                                 "abe_decrypt_time_total",
1737                                 GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us,
1738                                 GNUNET_YES);
1739       GNUNET_STATISTICS_update (stats,
1740                                 "abe_decrypt_count",
1741                                 1,
1742                                 GNUNET_YES);
1743
1744       attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
1745       attr_le->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize (data,
1746                                                               attr_len);
1747       attr_le->claim->version = ntohl(*(uint32_t*)rd->data);
1748       GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
1749                                    handle->attrs->list_tail,
1750                                    attr_le);
1751       GNUNET_free (data);
1752     }
1753   }
1754   if (NULL != handle->parallel_lookups_head)
1755     return; //Wait for more
1756   /* Else we are done */
1757
1758   /* Store ticket in DB */
1759   if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1760                                                &handle->ticket,
1761                                                handle->attrs))
1762   {
1763     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1764                 "Unable to store ticket after consume\n");
1765     GNUNET_break (0);
1766   }
1767
1768   GNUNET_SCHEDULER_cancel (handle->kill_task);
1769   attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (handle->attrs);
1770   env = GNUNET_MQ_msg_extra (crm,
1771                              attrs_len,
1772                              GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
1773   crm->id = htonl (handle->r_id);
1774   crm->attrs_len = htons (attrs_len);
1775   crm->identity = handle->ticket.identity;
1776   data_tmp = (char *) &crm[1];
1777   GNUNET_RECLAIM_ATTRIBUTE_list_serialize (handle->attrs,
1778                                             data_tmp);
1779   GNUNET_MQ_send (handle->client->mq, env);
1780   GNUNET_CONTAINER_DLL_remove (handle->client->consume_op_head,
1781                                handle->client->consume_op_tail,
1782                                handle);
1783   cleanup_consume_ticket_handle (handle);
1784 }
1785
1786 void
1787 abort_parallel_lookups2 (void *cls)
1788 {
1789   struct ConsumeTicketHandle *handle = cls;
1790   struct ParallelLookup *lu;
1791   struct ParallelLookup *tmp;
1792   struct AttributeResultMessage *arm;
1793   struct GNUNET_MQ_Envelope *env;
1794
1795   handle->kill_task = NULL;
1796   for (lu = handle->parallel_lookups_head;
1797        NULL != lu;) {
1798     GNUNET_GNS_lookup_cancel (lu->lookup_request);
1799     GNUNET_free (lu->label);
1800     tmp = lu->next;
1801     GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1802                                  handle->parallel_lookups_tail,
1803                                  lu);
1804     GNUNET_free (lu);
1805     lu = tmp;
1806   }
1807   env = GNUNET_MQ_msg (arm,
1808                        GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1809   arm->id = htonl (handle->r_id);
1810   arm->attr_len = htons (0);
1811   GNUNET_MQ_send (handle->client->mq, env);
1812
1813 }
1814
1815
1816 static void
1817 process_consume_abe_key (void *cls, uint32_t rd_count,
1818                          const struct GNUNET_GNSRECORD_Data *rd)
1819 {
1820   struct ConsumeTicketHandle *handle = cls;
1821   struct GNUNET_HashCode new_key_hash;
1822   struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1823   struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1824   struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1825   struct ParallelLookup *parallel_lookup;
1826   size_t size;
1827   char *buf;
1828   char *scope;
1829
1830   handle->lookup_request = NULL;
1831   if (1 != rd_count)
1832   {
1833     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1834                 "Number of keys %d != 1.",
1835                 rd_count);
1836     cleanup_consume_ticket_handle (handle);
1837     GNUNET_CONTAINER_DLL_remove (handle->client->consume_op_head,
1838                                  handle->client->consume_op_tail,
1839                                  handle);
1840     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1841     return;
1842   }
1843
1844   //Decrypt
1845   ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1846
1847   buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1848
1849   //Calculate symmetric key from ecdh parameters
1850   GNUNET_assert (GNUNET_OK == 
1851                  GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
1852                                            ecdh_key,
1853                                            &new_key_hash));
1854   create_sym_key_from_ecdh (&new_key_hash,
1855                             &enc_key,
1856                             &enc_iv);
1857   size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1858                                           rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1859                                           &enc_key,
1860                                           &enc_iv,
1861                                           buf);
1862
1863   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1864               "Decrypted bytes: %zd Expected bytes: %zd\n",
1865               size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1866   GNUNET_STATISTICS_update (stats,
1867                             "abe_key_lookup_time_total",
1868                             GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us,
1869                             GNUNET_YES);
1870   GNUNET_STATISTICS_update (stats,
1871                             "abe_key_lookups_count",
1872                             1,
1873                             GNUNET_YES);
1874   scopes = GNUNET_strdup (buf);
1875   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1876               "Scopes %s\n", scopes);
1877   handle->key = GNUNET_ABE_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1878                                                   rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1879                                                   - strlen (scopes) - 1);
1880
1881   for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1882   {
1883     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1884                 "Looking up %s\n", scope);
1885     parallel_lookup = GNUNET_new (struct ParallelLookup);
1886     parallel_lookup->handle = handle;
1887     parallel_lookup->label = GNUNET_strdup (scope);
1888     parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get();
1889     parallel_lookup->lookup_request
1890       = GNUNET_GNS_lookup (gns_handle,
1891                            scope,
1892                            &handle->ticket.identity,
1893                            GNUNET_GNSRECORD_TYPE_ID_ATTR,
1894                            GNUNET_GNS_LO_DEFAULT,
1895                            &process_parallel_lookup2,
1896                            parallel_lookup);
1897     GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1898                                  handle->parallel_lookups_tail,
1899                                  parallel_lookup);
1900   }
1901   GNUNET_free (scopes);
1902   GNUNET_free (buf);
1903   handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1904                                                     &abort_parallel_lookups2,
1905                                                     handle);
1906 }
1907
1908
1909 static void
1910 handle_consume_ticket_message (void *cls,
1911                                const struct ConsumeTicketMessage *cm)
1912 {
1913   struct ConsumeTicketHandle *ch;
1914   struct IdpClient *idp = cls;
1915   char* rnd_label;
1916
1917   ch = GNUNET_new (struct ConsumeTicketHandle);
1918   ch->r_id = ntohl (cm->id);
1919   ch->client = idp;
1920   ch->identity = cm->identity;
1921   ch->attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
1922   GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
1923                                       &ch->identity_pub);
1924   ch->ticket = *((struct GNUNET_RECLAIM_Ticket*)&cm[1]);
1925   rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
1926                                                    sizeof (uint64_t));
1927   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1928               "Looking for ABE key under %s\n", rnd_label);
1929   ch->lookup_start_time = GNUNET_TIME_absolute_get ();
1930   ch->lookup_request
1931     = GNUNET_GNS_lookup (gns_handle,
1932                          rnd_label,
1933                          &ch->ticket.identity,
1934                          GNUNET_GNSRECORD_TYPE_ABE_KEY,
1935                          GNUNET_GNS_LO_DEFAULT,
1936                          &process_consume_abe_key,
1937                          ch);
1938   GNUNET_CONTAINER_DLL_insert (idp->consume_op_head,
1939                                idp->consume_op_tail,
1940                                ch);
1941   GNUNET_free (rnd_label);
1942   GNUNET_SERVICE_client_continue (idp->client);
1943 }
1944
1945 /**
1946  * Cleanup attribute store handle
1947  *
1948  * @param handle handle to clean up
1949  */
1950 static void
1951 cleanup_as_handle (struct AttributeStoreHandle *handle)
1952 {
1953   if (NULL != handle->ns_qe)
1954     GNUNET_NAMESTORE_cancel (handle->ns_qe);
1955   if (NULL != handle->claim)
1956     GNUNET_free (handle->claim);
1957   if (NULL != handle->abe_key)
1958     GNUNET_ABE_cpabe_delete_master_key (handle->abe_key);
1959   GNUNET_free (handle);
1960 }
1961
1962 static void
1963 attr_store_cont (void *cls,
1964                  int32_t success,
1965                  const char *emsg)
1966 {
1967   struct AttributeStoreHandle *as_handle = cls;
1968   struct GNUNET_MQ_Envelope *env;
1969   struct AttributeStoreResultMessage *acr_msg;
1970
1971   as_handle->ns_qe = NULL;
1972   GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head,
1973                                as_handle->client->store_op_tail,
1974                                as_handle);
1975
1976   if (GNUNET_SYSERR == success)
1977   {
1978     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1979                 "Failed to store attribute %s\n",
1980                 emsg);
1981     cleanup_as_handle (as_handle);
1982     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1983     return;
1984   }
1985
1986   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1987               "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1988   env = GNUNET_MQ_msg (acr_msg,
1989                        GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE_RESPONSE);
1990   acr_msg->id = htonl (as_handle->r_id);
1991   acr_msg->op_result = htonl (GNUNET_OK);
1992   GNUNET_MQ_send (as_handle->client->mq,
1993                   env);
1994   cleanup_as_handle (as_handle);
1995 }
1996
1997 static void
1998 attr_store_task (void *cls)
1999 {
2000   struct AttributeStoreHandle *as_handle = cls;
2001   struct GNUNET_GNSRECORD_Data rd[1];
2002   char* buf;
2003   char* policy;
2004   char* enc_buf;
2005   char* rd_buf;
2006   size_t enc_size;
2007   size_t buf_size;
2008   uint32_t attr_ver;
2009
2010   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2011               "Storing attribute\n");
2012   buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (as_handle->claim);
2013   buf = GNUNET_malloc (buf_size);
2014
2015   GNUNET_RECLAIM_ATTRIBUTE_serialize (as_handle->claim,
2016                                        buf);
2017
2018   GNUNET_asprintf (&policy,
2019                    "%s_%lu",
2020                    as_handle->claim->name,
2021                    as_handle->claim->version);
2022   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2023               "Encrypting with policy %s\n", policy);
2024   /**
2025    * Encrypt the attribute value and store in namestore
2026    */
2027   enc_size = GNUNET_ABE_cpabe_encrypt (buf,
2028                                        buf_size,
2029                                        policy, //Policy
2030                                        as_handle->abe_key,
2031                                        (void**)&enc_buf);
2032   if (GNUNET_SYSERR == enc_size)
2033   {
2034     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2035                 "Failed to encrypt with policy %s\n",
2036                 policy);
2037     GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head,
2038                                  as_handle->client->store_op_tail,
2039                                  as_handle);
2040
2041     cleanup_as_handle (as_handle);
2042     GNUNET_free (buf);
2043     GNUNET_free (policy);
2044     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
2045     return;
2046   }
2047   GNUNET_free (buf);
2048   GNUNET_free (policy);
2049   rd[0].data_size = enc_size + sizeof (uint32_t);
2050   rd_buf = GNUNET_malloc (rd[0].data_size);
2051   attr_ver = htonl (as_handle->claim->version);
2052   GNUNET_memcpy (rd_buf,
2053                  &attr_ver,
2054                  sizeof (uint32_t));
2055   GNUNET_memcpy (rd_buf+sizeof (uint32_t),
2056                  enc_buf,
2057                  enc_size);
2058   rd[0].data = rd_buf;
2059   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
2060   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
2061   rd[0].expiration_time = as_handle->exp.rel_value_us;
2062   as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
2063                                                      &as_handle->identity,
2064                                                      as_handle->claim->name,
2065                                                      1,
2066                                                      rd,
2067                                                      &attr_store_cont,
2068                                                      as_handle);
2069   GNUNET_free (enc_buf);
2070   GNUNET_free (rd_buf);
2071 }
2072
2073
2074 static void
2075 store_after_abe_bootstrap (void *cls,
2076                            struct GNUNET_ABE_AbeMasterKey *abe_key)
2077 {
2078   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2079               "Finished ABE bootstrap\n");
2080   struct AttributeStoreHandle *ash = cls;
2081   ash->abe_key = abe_key;
2082   GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
2083 }
2084
2085 static int
2086 check_attribute_store_message(void *cls,
2087                               const struct AttributeStoreMessage *sam)
2088 {
2089   uint16_t size;
2090
2091   size = ntohs (sam->header.size);
2092   if (size <= sizeof (struct AttributeStoreMessage))
2093   {
2094     GNUNET_break (0);
2095     return GNUNET_SYSERR;
2096   }
2097   return GNUNET_OK;
2098 }
2099
2100
2101 static void
2102 handle_attribute_store_message (void *cls,
2103                                 const struct AttributeStoreMessage *sam)
2104 {
2105   struct AttributeStoreHandle *as_handle;
2106   struct IdpClient *idp = cls;
2107   size_t data_len;
2108   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2109               "Received ATTRIBUTE_STORE message\n");
2110
2111   data_len = ntohs (sam->attr_len);
2112
2113   as_handle = GNUNET_new (struct AttributeStoreHandle);
2114   as_handle->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char*)&sam[1],
2115                                                             data_len);
2116
2117   as_handle->r_id = ntohl (sam->id);
2118   as_handle->identity = sam->identity;
2119   as_handle->exp.rel_value_us = GNUNET_ntohll (sam->exp);
2120   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
2121                                       &as_handle->identity_pkey);
2122
2123   GNUNET_SERVICE_client_continue (idp->client);
2124   as_handle->client = idp;
2125   GNUNET_CONTAINER_DLL_insert (idp->store_op_head,
2126                                idp->store_op_tail,
2127                                as_handle);
2128   bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
2129 }
2130
2131 static void
2132 cleanup_attribute_iter_handle (struct AttributeIterator *ai)
2133 {
2134   if (NULL != ai->abe_key)
2135     GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
2136   GNUNET_free (ai);
2137 }
2138
2139 static void
2140 attr_iter_error (void *cls)
2141 {
2142   struct AttributeIterator *ai = cls;
2143   //TODO
2144   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2145               "Failed to iterate over attributes\n");
2146   GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
2147                                ai->client->attr_iter_tail,
2148                                ai);
2149   cleanup_attribute_iter_handle (ai);
2150   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
2151 }
2152
2153 static void
2154 attr_iter_finished (void *cls)
2155 {
2156   struct AttributeIterator *ai = cls;
2157   struct GNUNET_MQ_Envelope *env;
2158   struct AttributeResultMessage *arm;
2159
2160   env = GNUNET_MQ_msg (arm,
2161                        GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
2162   arm->id = htonl (ai->request_id);
2163   arm->attr_len = htons (0);
2164   GNUNET_MQ_send (ai->client->mq, env);
2165   GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
2166                                ai->client->attr_iter_tail,
2167                                ai);
2168   cleanup_attribute_iter_handle (ai);
2169 }
2170
2171 static void
2172 attr_iter_cb (void *cls,
2173               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
2174               const char *label,
2175               unsigned int rd_count,
2176               const struct GNUNET_GNSRECORD_Data *rd)
2177 {
2178   struct AttributeIterator *ai = cls;
2179   struct AttributeResultMessage *arm;
2180   struct GNUNET_ABE_AbeKey *key;
2181   struct GNUNET_MQ_Envelope *env;
2182   ssize_t msg_extra_len;
2183   char* attr_ser;
2184   char* attrs[2];
2185   char* data_tmp;
2186   char* policy;
2187   uint32_t attr_ver;
2188
2189   if (rd_count != 1)
2190   {
2191     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
2192                                          1);
2193     return;
2194   }
2195
2196   if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type)
2197   {
2198     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
2199                                          1);
2200     return;
2201   }
2202   attr_ver = ntohl(*((uint32_t*)rd->data));
2203   GNUNET_asprintf (&policy, "%s_%lu",
2204                    label, attr_ver);
2205   attrs[0] = policy;
2206   attrs[1] = 0;
2207   key = GNUNET_ABE_cpabe_create_key (ai->abe_key,
2208                                      attrs);
2209   msg_extra_len = GNUNET_ABE_cpabe_decrypt (rd->data+sizeof (uint32_t),
2210                                             rd->data_size-sizeof (uint32_t),
2211                                             key,
2212                                             (void**)&attr_ser);
2213   if (GNUNET_SYSERR == msg_extra_len)
2214   {
2215     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
2216                                          1);
2217     return;
2218   }
2219
2220   GNUNET_ABE_cpabe_delete_key (key,
2221                                GNUNET_YES);
2222   //GNUNET_free (policy);
2223   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2224               "Found attribute: %s\n", label);
2225   env = GNUNET_MQ_msg_extra (arm,
2226                              msg_extra_len,
2227                              GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
2228   arm->id = htonl (ai->request_id);
2229   arm->attr_len = htons (msg_extra_len);
2230   GNUNET_CRYPTO_ecdsa_key_get_public (zone,
2231                                       &arm->identity);
2232   data_tmp = (char *) &arm[1];
2233   GNUNET_memcpy (data_tmp,
2234                  attr_ser,
2235                  msg_extra_len);
2236   GNUNET_MQ_send (ai->client->mq, env);
2237   GNUNET_free (attr_ser);
2238   GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
2239   ai->abe_key = NULL;
2240 }
2241
2242
2243 void
2244 iterate_after_abe_bootstrap (void *cls,
2245                              struct GNUNET_ABE_AbeMasterKey *abe_key)
2246 {
2247   struct AttributeIterator *ai = cls;
2248   ai->abe_key = abe_key;
2249   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
2250                                                      &ai->identity,
2251                                                      &attr_iter_error,
2252                                                      ai,
2253                                                      &attr_iter_cb,
2254                                                      ai,
2255                                                      &attr_iter_finished,
2256                                                      ai);
2257 }
2258
2259
2260 static void
2261 iterate_next_after_abe_bootstrap (void *cls,
2262                                   struct GNUNET_ABE_AbeMasterKey *abe_key)
2263 {
2264   struct AttributeIterator *ai = cls;
2265   ai->abe_key = abe_key;
2266   GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
2267                                        1);
2268 }
2269
2270
2271
2272 static void
2273 handle_iteration_start (void *cls,
2274                         const struct AttributeIterationStartMessage *ais_msg)
2275 {
2276   struct IdpClient *idp = cls;
2277   struct AttributeIterator *ai;
2278
2279   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2280               "Received ATTRIBUTE_ITERATION_START message\n");
2281   ai = GNUNET_new (struct AttributeIterator);
2282   ai->request_id = ntohl (ais_msg->id);
2283   ai->client = idp;
2284   ai->identity = ais_msg->identity;
2285
2286   GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head,
2287                                idp->attr_iter_tail,
2288                                ai);
2289   bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
2290   GNUNET_SERVICE_client_continue (idp->client);
2291 }
2292
2293
2294 static void
2295 handle_iteration_stop (void *cls,
2296                        const struct AttributeIterationStopMessage *ais_msg)
2297 {
2298   struct IdpClient *idp = cls;
2299   struct AttributeIterator *ai;
2300   uint32_t rid;
2301
2302   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2303               "Received `%s' message\n",
2304               "ATTRIBUTE_ITERATION_STOP");
2305   rid = ntohl (ais_msg->id);
2306   for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
2307     if (ai->request_id == rid)
2308       break;
2309   if (NULL == ai)
2310   {
2311     GNUNET_break (0);
2312     GNUNET_SERVICE_client_drop (idp->client);
2313     return;
2314   }
2315   GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head,
2316                                idp->attr_iter_tail,
2317                                ai);
2318   GNUNET_free (ai);
2319   GNUNET_SERVICE_client_continue (idp->client);
2320 }
2321
2322
2323 static void
2324 handle_iteration_next (void *cls,
2325                        const struct AttributeIterationNextMessage *ais_msg)
2326 {
2327   struct IdpClient *idp = cls;
2328   struct AttributeIterator *ai;
2329   uint32_t rid;
2330
2331   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2332               "Received ATTRIBUTE_ITERATION_NEXT message\n");
2333   rid = ntohl (ais_msg->id);
2334   for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
2335     if (ai->request_id == rid)
2336       break;
2337   if (NULL == ai)
2338   {
2339     GNUNET_break (0);
2340     GNUNET_SERVICE_client_drop (idp->client);
2341     return;
2342   }
2343   bootstrap_abe (&ai->identity,
2344                  &iterate_next_after_abe_bootstrap,
2345                  ai,
2346                  GNUNET_NO);
2347   GNUNET_SERVICE_client_continue (idp->client);
2348 }
2349
2350 /**
2351  * Ticket iteration processor result
2352  */
2353 enum ZoneIterationResult
2354 {
2355   /**
2356    * Iteration start.
2357    */
2358   IT_START = 0,
2359
2360   /**
2361    * Found tickets,
2362    * Continue to iterate with next iteration_next call
2363    */
2364   IT_SUCCESS_MORE_AVAILABLE = 1,
2365
2366   /**
2367    * Iteration complete
2368    */
2369   IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
2370 };
2371
2372
2373 /**
2374  * Context for ticket iteration
2375  */
2376 struct TicketIterationProcResult
2377 {
2378   /**
2379    * The ticket iteration handle
2380    */
2381   struct TicketIteration *ti;
2382
2383   /**
2384    * Iteration result: iteration done?
2385    * #IT_SUCCESS_MORE_AVAILABLE:  if there may be more results overall but
2386    * we got one for now and have sent it to the client
2387    * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
2388    * #IT_START: if we are still trying to find a result.
2389    */
2390   int res_iteration_finished;
2391
2392 };
2393
2394 static void
2395 cleanup_ticket_iter_handle (struct TicketIteration *ti)
2396 {
2397   GNUNET_free (ti);
2398 }
2399
2400 /**
2401  * Process ticket from database
2402  *
2403  * @param cls struct TicketIterationProcResult
2404  * @param ticket the ticket
2405  * @param attrs the attributes
2406  */
2407 static void
2408 ticket_iterate_proc (void *cls,
2409                      const struct GNUNET_RECLAIM_Ticket *ticket,
2410                      const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
2411 {
2412   struct TicketIterationProcResult *proc = cls;
2413
2414   if (NULL == ticket)
2415   {
2416     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2417                 "Iteration done\n");
2418     proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2419     return;
2420   }
2421   proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
2422   send_ticket_result (proc->ti->client,
2423                       proc->ti->r_id,
2424                       ticket,
2425                       attrs);
2426
2427 }
2428
2429 /**
2430  * Perform ticket iteration step
2431  *
2432  * @param ti ticket iterator to process
2433  */
2434 static void
2435 run_ticket_iteration_round (struct TicketIteration *ti)
2436 {
2437   struct TicketIterationProcResult proc;
2438   struct GNUNET_MQ_Envelope *env;
2439   struct TicketResultMessage *trm;
2440   int ret;
2441
2442   memset (&proc, 0, sizeof (proc));
2443   proc.ti = ti;
2444   proc.res_iteration_finished = IT_START;
2445   while (IT_START == proc.res_iteration_finished)
2446   {
2447     if (GNUNET_SYSERR ==
2448         (ret = TKT_database->iterate_tickets (TKT_database->cls,
2449                                               &ti->identity,
2450                                               ti->is_audience,
2451                                               ti->offset,
2452                                               &ticket_iterate_proc,
2453                                               &proc)))
2454     {
2455       GNUNET_break (0);
2456       break;
2457     }
2458     if (GNUNET_NO == ret)
2459       proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2460     ti->offset++;
2461   }
2462   if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
2463   {
2464     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2465                 "More results available\n");
2466     return; /* more later */
2467   }
2468   /* send empty response to indicate end of list */
2469   env = GNUNET_MQ_msg (trm,
2470                        GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
2471   trm->id = htonl (ti->r_id);
2472   GNUNET_MQ_send (ti->client->mq,
2473                   env);
2474   GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2475                                ti->client->ticket_iter_tail,
2476                                ti);
2477   cleanup_ticket_iter_handle (ti);
2478 }
2479
2480 static void
2481 handle_ticket_iteration_start (void *cls,
2482                                const struct TicketIterationStartMessage *tis_msg)
2483 {
2484   struct IdpClient *client = cls;
2485   struct TicketIteration *ti;
2486
2487   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2488               "Received TICKET_ITERATION_START message\n");
2489   ti = GNUNET_new (struct TicketIteration);
2490   ti->r_id = ntohl (tis_msg->id);
2491   ti->offset = 0;
2492   ti->client = client;
2493   ti->identity = tis_msg->identity;
2494   ti->is_audience = ntohl (tis_msg->is_audience);
2495
2496   GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2497                                client->ticket_iter_tail,
2498                                ti);
2499   run_ticket_iteration_round (ti);
2500   GNUNET_SERVICE_client_continue (client->client);
2501 }
2502
2503
2504 static void
2505 handle_ticket_iteration_stop (void *cls,
2506                               const struct TicketIterationStopMessage *tis_msg)
2507 {
2508   struct IdpClient *client = cls;
2509   struct TicketIteration *ti;
2510   uint32_t rid;
2511
2512   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2513               "Received `%s' message\n",
2514               "TICKET_ITERATION_STOP");
2515   rid = ntohl (tis_msg->id);
2516   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2517     if (ti->r_id == rid)
2518       break;
2519   if (NULL == ti)
2520   {
2521     GNUNET_break (0);
2522     GNUNET_SERVICE_client_drop (client->client);
2523     return;
2524   }
2525   GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2526                                client->ticket_iter_tail,
2527                                ti);
2528   cleanup_ticket_iter_handle (ti);
2529   GNUNET_SERVICE_client_continue (client->client);
2530 }
2531
2532
2533 static void
2534 handle_ticket_iteration_next (void *cls,
2535                               const struct TicketIterationNextMessage *tis_msg)
2536 {
2537   struct IdpClient *client = cls;
2538   struct TicketIteration *ti;
2539   uint32_t rid;
2540
2541   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2542               "Received TICKET_ITERATION_NEXT message\n");
2543   rid = ntohl (tis_msg->id);
2544   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2545     if (ti->r_id == rid)
2546       break;
2547   if (NULL == ti)
2548   {
2549     GNUNET_break (0);
2550     GNUNET_SERVICE_client_drop (client->client);
2551     return;
2552   }
2553   run_ticket_iteration_round (ti);
2554   GNUNET_SERVICE_client_continue (client->client);
2555 }
2556
2557
2558
2559
2560 /**
2561  * Main function that will be run
2562  *
2563  * @param cls closure
2564  * @param c the configuration used 
2565  * @param server the service handle
2566  */
2567 static void
2568 run (void *cls,
2569      const struct GNUNET_CONFIGURATION_Handle *c,
2570      struct GNUNET_SERVICE_Handle *server)
2571 {
2572   char *database;
2573   cfg = c;
2574
2575   stats = GNUNET_STATISTICS_create ("reclaim", cfg);
2576
2577   //Connect to identity and namestore services
2578   ns_handle = GNUNET_NAMESTORE_connect (cfg);
2579   if (NULL == ns_handle)
2580   {
2581     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
2582   }
2583
2584   gns_handle = GNUNET_GNS_connect (cfg);
2585   if (NULL == gns_handle)
2586   {
2587     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
2588   }
2589   credential_handle = GNUNET_CREDENTIAL_connect (cfg);
2590   if (NULL == credential_handle)
2591   {
2592     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
2593   }
2594   identity_handle = GNUNET_IDENTITY_connect (cfg,
2595                                              NULL,
2596                                              NULL);
2597   /* Loading DB plugin */
2598   if (GNUNET_OK !=
2599       GNUNET_CONFIGURATION_get_value_string (cfg,
2600                                              "reclaim",
2601                                              "database",
2602                                              &database))
2603     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2604                 "No database backend configured\n");
2605   GNUNET_asprintf (&db_lib_name,
2606                    "libgnunet_plugin_reclaim_%s",
2607                    database);
2608   TKT_database = GNUNET_PLUGIN_load (db_lib_name,
2609                                      (void *) cfg);
2610   GNUNET_free (database);
2611   if (NULL == TKT_database)
2612   {
2613     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2614                 "Could not load database backend `%s'\n",
2615                 db_lib_name);
2616     GNUNET_SCHEDULER_shutdown ();
2617     return;
2618   }
2619
2620   if (GNUNET_OK ==
2621       GNUNET_CONFIGURATION_get_value_time (cfg,
2622                                            "reclaim",
2623                                            "TOKEN_EXPIRATION_INTERVAL",
2624                                            &token_expiration_interval))
2625   {
2626     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2627                 "Time window for zone iteration: %s\n",
2628                 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
2629                                                         GNUNET_YES));
2630   } else {
2631     token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
2632   }
2633
2634   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2635 }
2636
2637 /**
2638  * Called whenever a client is disconnected.
2639  *
2640  * @param cls closure
2641  * @param client identification of the client
2642  * @param app_ctx @a client
2643  */
2644 static void
2645 client_disconnect_cb (void *cls,
2646                       struct GNUNET_SERVICE_Client *client,
2647                       void *app_ctx)
2648 {
2649   struct IdpClient *idp = app_ctx;
2650   struct AttributeIterator *ai;
2651   struct TicketIteration *ti;
2652   struct TicketRevocationHandle *rh;
2653   struct TicketIssueHandle *iss;
2654   struct ConsumeTicketHandle *ct;
2655   struct AttributeStoreHandle *as;
2656
2657   //TODO other operations
2658
2659   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2660               "Client %p disconnected\n",
2661               client);
2662
2663   while (NULL != (iss = idp->issue_op_head))
2664   {
2665     GNUNET_CONTAINER_DLL_remove (idp->issue_op_head,
2666                                  idp->issue_op_tail,
2667                                  iss);
2668     cleanup_ticket_issue_handle (iss);
2669   }
2670   while (NULL != (ct = idp->consume_op_head))
2671   {
2672     GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
2673                                  idp->consume_op_tail,
2674                                  ct);
2675     cleanup_consume_ticket_handle (ct);
2676   }
2677   while (NULL != (as = idp->store_op_head))
2678   {
2679     GNUNET_CONTAINER_DLL_remove (idp->store_op_head,
2680                                  idp->store_op_tail,
2681                                  as);
2682     cleanup_as_handle (as);
2683   }
2684
2685   while (NULL != (ai = idp->attr_iter_head))
2686   {
2687     GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head,
2688                                  idp->attr_iter_tail,
2689                                  ai);
2690     cleanup_attribute_iter_handle (ai);
2691   }
2692   while (NULL != (rh = idp->revoke_op_head))
2693   {
2694     GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head,
2695                                  idp->revoke_op_tail,
2696                                  rh);
2697     cleanup_revoke_ticket_handle (rh);
2698   }
2699   while (NULL != (ti = idp->ticket_iter_head))
2700   {
2701     GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
2702                                  idp->ticket_iter_tail,
2703                                  ti);
2704     cleanup_ticket_iter_handle (ti);
2705   }
2706   GNUNET_free (idp);
2707 }
2708
2709
2710 /**
2711  * Add a client to our list of active clients.
2712  *
2713  * @param cls NULL
2714  * @param client client to add
2715  * @param mq message queue for @a client
2716  * @return internal namestore client structure for this client
2717  */
2718 static void *
2719 client_connect_cb (void *cls,
2720                    struct GNUNET_SERVICE_Client *client,
2721                    struct GNUNET_MQ_Handle *mq)
2722 {
2723   struct IdpClient *idp;
2724   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2725               "Client %p connected\n",
2726               client);
2727   idp = GNUNET_new (struct IdpClient);
2728   idp->client = client;
2729   idp->mq = mq;
2730   return idp;
2731 }
2732
2733
2734
2735 /**
2736  * Define "main" method using service macro.
2737  */
2738 GNUNET_SERVICE_MAIN
2739 ("reclaim",
2740  GNUNET_SERVICE_OPTION_NONE,
2741  &run,
2742  &client_connect_cb,
2743  &client_disconnect_cb,
2744  NULL,
2745  GNUNET_MQ_hd_var_size (attribute_store_message,
2746                         GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
2747                         struct AttributeStoreMessage,
2748                         NULL),
2749  GNUNET_MQ_hd_fixed_size (iteration_start, 
2750                           GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
2751                           struct AttributeIterationStartMessage,
2752                           NULL),
2753  GNUNET_MQ_hd_fixed_size (iteration_next, 
2754                           GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
2755                           struct AttributeIterationNextMessage,
2756                           NULL),
2757  GNUNET_MQ_hd_fixed_size (iteration_stop, 
2758                           GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
2759                           struct AttributeIterationStopMessage,
2760                           NULL),
2761  GNUNET_MQ_hd_var_size (issue_ticket_message,
2762                         GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
2763                         struct IssueTicketMessage,
2764                         NULL),
2765  GNUNET_MQ_hd_var_size (consume_ticket_message,
2766                         GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
2767                         struct ConsumeTicketMessage,
2768                         NULL),
2769  GNUNET_MQ_hd_fixed_size (ticket_iteration_start, 
2770                           GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
2771                           struct TicketIterationStartMessage,
2772                           NULL),
2773  GNUNET_MQ_hd_fixed_size (ticket_iteration_next, 
2774                           GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
2775                           struct TicketIterationNextMessage,
2776                           NULL),
2777  GNUNET_MQ_hd_fixed_size (ticket_iteration_stop, 
2778                           GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
2779                           struct TicketIterationStopMessage,
2780                           NULL),
2781  GNUNET_MQ_hd_var_size (revoke_ticket_message,
2782                         GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
2783                         struct RevokeTicketMessage,
2784                         NULL),
2785  GNUNET_MQ_handler_end());
2786 /* end of gnunet-service-reclaim.c */