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