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