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