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