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