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