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