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