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