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