-remove deprecated
[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 #include <inttypes.h>
41
42 /**
43  * First pass state
44  */
45 #define STATE_INIT 0
46
47 /**
48  * Normal operation state
49  */
50 #define STATE_POST_INIT 1
51
52 /**
53  * Minimum interval between updates
54  */
55 #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
56
57 /**
58  * Standard token expiration time
59  */
60 #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
61
62 /**
63  * Identity handle
64  */
65 static struct GNUNET_IDENTITY_Handle *identity_handle;
66
67 /**
68  * Database handle
69  */
70 static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database;
71
72 /**
73  * Name of DB plugin
74  */
75 static char *db_lib_name;
76
77 /**
78  * Token expiration interval
79  */
80 static struct GNUNET_TIME_Relative token_expiration_interval;
81
82 /**
83  * Namestore handle
84  */
85 static struct GNUNET_NAMESTORE_Handle *ns_handle;
86
87 /**
88  * GNS handle
89  */
90 static struct GNUNET_GNS_Handle *gns_handle;
91
92 /**
93  * Credential handle
94  */
95 static struct GNUNET_CREDENTIAL_Handle *credential_handle;
96
97 /**
98  * Namestore qe
99  */
100 static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
101
102 /**
103  * Namestore iterator
104  */
105 static struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
106
107 /**
108  * Timeout task
109  */
110 static struct GNUNET_SCHEDULER_Task *timeout_task;
111
112 /**
113  * Update task
114  */
115 static struct GNUNET_SCHEDULER_Task *update_task;
116
117
118 /**
119  * Currently processed token
120  */
121 static struct IdentityToken *token;
122
123 /**
124  * Label for currently processed token
125  */
126 static char* label;
127
128 /**
129  * Scopes for processed token
130  */
131 static char* scopes;
132
133 /**
134  * Handle to the statistics service.
135  */
136 static struct GNUNET_STATISTICS_Handle *stats;
137
138 /**
139  * Our configuration.
140  */
141 static const struct GNUNET_CONFIGURATION_Handle *cfg;
142
143 /**
144  * An idp client
145  */
146 struct IdpClient;
147
148 /**
149  * A ticket iteration operation.
150  */
151 struct TicketIteration
152 {
153   /**
154    * DLL
155    */
156   struct TicketIteration *next;
157
158   /**
159    * DLL
160    */
161   struct TicketIteration *prev;
162
163   /**
164    * Client which intiated this zone iteration
165    */
166   struct IdpClient *client;
167
168   /**
169    * Key of the identity we are iterating over.
170    */
171   struct GNUNET_CRYPTO_EcdsaPublicKey identity;
172
173   /**
174    * Identity is audience
175    */
176   uint32_t is_audience;
177
178   /**
179    * The operation id fot the iteration in the response for the client
180    */
181   uint32_t r_id;
182
183   /**
184    * Offset of the iteration used to address next result of the 
185    * iteration in the store
186    *
187    * Initialy set to 0 in handle_iteration_start
188    * Incremented with by every call to handle_iteration_next
189    */
190   uint32_t offset;
191
192 };
193
194
195
196 /**
197  * Callback after an ABE bootstrap
198  *
199  * @param cls closure
200  * @param abe_key the ABE key that exists or was created
201  */
202 typedef void
203 (*AbeBootstrapResult) (void *cls,
204                        struct GNUNET_CRYPTO_AbeMasterKey *abe_key);
205
206
207 struct AbeBootstrapHandle
208 {
209   /**
210    * Function to call when finished
211    */
212   AbeBootstrapResult proc;
213
214   /**
215    * Callback closure
216    */
217   char *proc_cls;
218
219   /**
220    * Key of the zone we are iterating over.
221    */
222   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
223
224   /**
225    * Namestore Queue Entry
226    */
227   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
228
229   /**
230    * The issuer egos ABE master key
231    */
232   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
233 };
234
235 /**
236  * An attribute iteration operation.
237  */
238 struct AttributeIterator
239 {
240   /**
241    * Next element in the DLL
242    */
243   struct AttributeIterator *next;
244
245   /**
246    * Previous element in the DLL
247    */
248   struct AttributeIterator *prev;
249
250   /**
251    * IDP client which intiated this zone iteration
252    */
253   struct IdpClient *client;
254
255   /**
256    * Key of the zone we are iterating over.
257    */
258   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
259
260   /**
261    * The issuer egos ABE master key
262    */
263   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
264
265   /**
266    * Namestore iterator
267    */
268   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
269
270   /**
271    * The operation id fot the zone iteration in the response for the client
272    */
273   uint32_t request_id;
274
275 };
276
277
278
279 /**
280  * An idp client
281  */
282 struct IdpClient
283 {
284
285   /**
286    * The client
287    */
288   struct GNUNET_SERVICE_Client *client;
289
290   /**
291    * Message queue for transmission to @e client
292    */
293   struct GNUNET_MQ_Handle *mq;
294   
295   /**
296    * Head of the DLL of
297    * Attribute iteration operations in 
298    * progress initiated by this client
299    */
300   struct AttributeIterator *op_head;
301
302   /**
303    * Tail of the DLL of
304    * Attribute iteration operations 
305    * in progress initiated by this client
306    */
307   struct AttributeIterator *op_tail;
308
309   /**
310    * Head of DLL of ticket iteration ops
311    */
312   struct TicketIteration *ticket_iter_head;
313
314   /**
315    * Tail of DLL of ticket iteration ops
316    */
317   struct TicketIteration *ticket_iter_tail;
318 };
319
320
321
322 struct AttributeStoreHandle
323 {
324
325   /**
326    * Client connection
327    */
328   struct IdpClient *client;
329
330   /**
331    * Identity
332    */
333   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
334
335   /**
336    * Identity pubkey
337    */
338   struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
339
340   /**
341    * The issuer egos ABE master key
342    */
343   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
344
345   /**
346    * QueueEntry
347    */
348   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
349
350   /**
351    * The attribute to store
352    */
353   struct GNUNET_IDENTITY_PROVIDER_Attribute *attribute;
354
355   /**
356    * request id
357    */
358   uint32_t r_id;
359 };
360
361
362 /* Prototype */
363 struct ParallelLookup;
364
365 struct ConsumeTicketHandle
366 {
367
368   /**
369    * Client connection
370    */
371   struct IdpClient *client;
372
373   /**
374    * Ticket
375    */
376   struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
377
378   /**
379    * LookupRequest
380    */
381   struct GNUNET_GNS_LookupRequest *lookup_request;
382
383   /**
384    * Audience Key
385    */
386   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
387
388   /**
389    * Audience Key
390    */
391   struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
392
393   /**
394    * Lookup DLL
395    */
396   struct ParallelLookup *parallel_lookups_head;
397
398   /**
399    * Lookup DLL
400    */
401   struct ParallelLookup *parallel_lookups_tail;
402   
403   /**
404    * Kill task
405    */
406   struct GNUNET_SCHEDULER_Task *kill_task;
407
408   /**
409    * The ABE key
410    */
411   struct GNUNET_CRYPTO_AbeKey *key;
412
413   /**
414    * Attributes
415    */
416   struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
417
418   /**
419    * request id
420    */
421   uint32_t r_id;
422 };
423
424 /**
425  * Handle for a parallel GNS lookup job
426  */
427 struct ParallelLookup
428 {
429   /* DLL */
430   struct ParallelLookup *next;
431
432   /* DLL */
433   struct ParallelLookup *prev;
434
435   /* The GNS request */
436   struct GNUNET_GNS_LookupRequest *lookup_request;
437
438   /* The handle the return to */
439   struct ConsumeTicketHandle *handle;
440
441   /* The label to look up */
442   char *label;
443 };
444
445 /**
446  * Ticket issue request handle
447  */
448 struct TicketIssueHandle
449 {
450
451   /**
452    * Client connection
453    */
454   struct IdpClient *client;
455
456   /**
457    * Attributes to issue
458    */
459   struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
460
461   /**
462    * Issuer Key
463    */
464   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
465
466   /**
467    * Ticket to issue
468    */
469   struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
470
471   /**
472    * QueueEntry
473    */
474   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
475
476   /**
477    * request id
478    */
479   uint32_t r_id;
480 };
481
482
483 /**
484  * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
485  *
486  */
487 struct EgoEntry
488 {
489   /**
490    * DLL
491    */
492   struct EgoEntry *next;
493
494   /**
495    * DLL
496    */
497   struct EgoEntry *prev;
498
499   /**
500    * Ego handle
501    */
502   struct GNUNET_IDENTITY_Ego *ego;
503
504   /**
505    * Attribute map. Contains the attributes as json_t
506    */
507   struct GNUNET_CONTAINER_MultiHashMap *attr_map;
508
509 };
510
511 /**
512  * Cleanup task
513  */
514 static void
515 cleanup()
516 {
517   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
518               "Cleaning up\n");
519   if (NULL != stats)
520   {
521     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
522     stats = NULL;
523   }
524   GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
525                                               TKT_database)); 
526   GNUNET_free (db_lib_name);
527   db_lib_name = NULL;
528   if (NULL != timeout_task)
529     GNUNET_SCHEDULER_cancel (timeout_task);
530   if (NULL != update_task)
531     GNUNET_SCHEDULER_cancel (update_task);
532   if (NULL != identity_handle)
533     GNUNET_IDENTITY_disconnect (identity_handle);
534   if (NULL != gns_handle)
535     GNUNET_GNS_disconnect (gns_handle);
536   if (NULL != credential_handle)
537     GNUNET_CREDENTIAL_disconnect (credential_handle);
538   if (NULL != ns_it)
539     GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
540   if (NULL != ns_qe)
541     GNUNET_NAMESTORE_cancel (ns_qe);
542   if (NULL != ns_handle)
543     GNUNET_NAMESTORE_disconnect (ns_handle);
544   if (NULL != token)
545     GNUNET_free (token);
546   if (NULL != label)
547     GNUNET_free (label);
548
549 }
550
551 /**
552  * Shutdown task
553  *
554  * @param cls NULL
555  * @param tc task context
556  */
557 static void
558 do_shutdown (void *cls)
559 {
560   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
561               "Shutting down...\n");
562   cleanup();
563 }
564
565 /**
566  * Finished storing newly bootstrapped ABE key
567  */
568 static void
569 bootstrap_store_cont (void *cls,
570                       int32_t success,
571                       const char *emsg)
572 {
573   struct AbeBootstrapHandle *abh = cls;
574   if (GNUNET_SYSERR == success)
575   {
576     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
577                 "Failed to bootstrap ABE master %s\n",
578                 emsg);
579     abh->proc (abh->proc_cls, NULL);
580     GNUNET_free (abh->abe_key);
581     GNUNET_free (abh);
582     return;
583   }
584   abh->proc (abh->proc_cls, abh->abe_key);
585   GNUNET_free (abh);
586 }
587
588 /**
589  * Generates and stores a new ABE key
590  */
591 static void
592 bootstrap_store_task (void *cls)
593 {
594   struct AbeBootstrapHandle *abh = cls;
595   struct GNUNET_GNSRECORD_Data rd[1];
596
597   rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (abh->abe_key,
598                                                               (void**)&rd[0].data);
599   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
600   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
601   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
602   abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
603                                                &abh->identity,
604                                                "+",
605                                                1,
606                                                rd,
607                                                &bootstrap_store_cont,
608                                                abh);
609 }
610
611 /**
612  * Error checking for ABE master
613  */
614 static void
615 bootstrap_abe_error (void *cls)
616 {
617   struct AbeBootstrapHandle *abh = cls;
618   GNUNET_free (abh);
619   abh->proc (abh->proc_cls, NULL);
620   GNUNET_free (abh);
621 }
622
623
624 /**
625  * Handle ABE lookup in namestore
626  */
627 static void
628 bootstrap_abe_result (void *cls,
629                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
630                       const char *label,
631                       unsigned int rd_count,
632                       const struct GNUNET_GNSRECORD_Data *rd)
633 {
634   struct AbeBootstrapHandle *abh = cls;
635   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
636   int i;
637
638   for (i=0;i<rd_count;i++) {
639     if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
640       continue;
641     abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key ((void**)rd[i].data,
642                                                           rd[i].data_size);
643     abh->proc (abh->proc_cls, abe_key);
644     GNUNET_free (abh);
645     return;
646   }
647
648   //No ABE master found, bootstrapping...
649   abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
650   GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
651 }
652
653 /**
654  * Bootstrap ABE master if it does not yet exists.
655  * Will call the AbeBootstrapResult processor when done.
656  */
657 static void
658 bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
659                AbeBootstrapResult proc,
660                void* cls)
661 {
662   struct AbeBootstrapHandle *abh;
663
664   abh = GNUNET_new (struct AbeBootstrapHandle);
665   abh->proc = proc;
666   abh->proc_cls = cls;
667   abh->identity = *identity;
668   abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
669                                                 identity,
670                                                 "+",
671                                                 &bootstrap_abe_error,
672                                                 abh,
673                                                 &bootstrap_abe_result,
674                                                 abh);
675
676 }
677
678
679
680 static int
681 create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
682                          struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
683                          struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
684 {
685   struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
686
687   GNUNET_CRYPTO_hash_to_enc (new_key_hash,
688                              &new_key_hash_str);
689   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
690   static const char ctx_key[] = "gnuid-aes-ctx-key";
691   GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
692                      new_key_hash, sizeof (struct GNUNET_HashCode),
693                      ctx_key, strlen (ctx_key),
694                      NULL, 0);
695   static const char ctx_iv[] = "gnuid-aes-ctx-iv";
696   GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
697                      new_key_hash, sizeof (struct GNUNET_HashCode),
698                      ctx_iv, strlen (ctx_iv),
699                      NULL, 0);
700   return GNUNET_OK;
701 }
702
703 static void
704 cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
705 {
706   if (NULL != handle->attrs)
707     attribute_list_destroy (handle->attrs);
708   if (NULL != handle->ns_qe)
709     GNUNET_NAMESTORE_cancel (handle->ns_qe);
710   GNUNET_free (handle);
711 }
712
713
714 static void
715 send_ticket_result (struct IdpClient *client,
716                     uint32_t r_id,
717                     const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
718 {
719   struct TicketResultMessage *irm;
720   struct GNUNET_MQ_Envelope *env;
721   struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
722
723   /* store ticket in DB */
724   if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
725                                                ticket))
726   {
727     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
728                 "Unable to store ticket after issue\n");
729     GNUNET_break (0);
730   }
731
732   env = GNUNET_MQ_msg_extra (irm,
733                              sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
734                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
735   ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
736   *ticket_buf = *ticket;
737   irm->id = htonl (r_id);
738   GNUNET_MQ_send (client->mq,
739                   env);
740 }
741
742 static void
743 store_ticket_issue_cont (void *cls,
744                          int32_t success,
745                          const char *emsg)
746 {
747   struct TicketIssueHandle *handle = cls;
748
749   handle->ns_qe = NULL;
750   if (GNUNET_SYSERR == success)
751   {
752     cleanup_ticket_issue_handle (handle);
753     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
754                 "Unknown Error\n");
755     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
756     return;
757   }
758   send_ticket_result (handle->client,
759                       handle->r_id,
760                       &handle->ticket);
761   cleanup_ticket_issue_handle (handle);
762 }
763
764
765
766 int
767 serialize_abe_keyinfo2 (const struct TicketIssueHandle *handle,
768                         const struct GNUNET_CRYPTO_AbeKey *rp_key,
769                         struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
770                         char **result)
771 {
772   struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
773   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
774   char *enc_keyinfo;
775   char *serialized_key;
776   char *buf;
777   char *write_ptr;
778   char attrs_str_len;
779   ssize_t size;
780
781   struct GNUNET_CRYPTO_SymmetricSessionKey skey;
782   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
783   struct GNUNET_HashCode new_key_hash;
784   ssize_t enc_size;
785
786   size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key,
787                                             (void**)&serialized_key);
788   attrs_str_len = 0;
789   for (le = handle->attrs->list_head; NULL != le; le = le->next) {
790     attrs_str_len += strlen (le->attribute->name) + 1;
791   }
792   buf = GNUNET_malloc (attrs_str_len + size);
793   write_ptr = buf;
794   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
795               "Writing attributes\n");
796   for (le = handle->attrs->list_head; NULL != le; le = le->next) {
797     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
798                 "%s\n", le->attribute->name);
799
800
801     GNUNET_memcpy (write_ptr,
802                    le->attribute->name,
803                    strlen (le->attribute->name));
804     write_ptr[strlen (le->attribute->name)] = ',';
805     write_ptr += strlen (le->attribute->name) + 1;
806   }
807   write_ptr--;
808   write_ptr[0] = '\0'; //replace last , with a 0-terminator
809   write_ptr++;
810   GNUNET_memcpy (write_ptr,
811                  serialized_key,
812                  size);
813   // ECDH keypair E = eG
814   *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
815   GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
816                                       &ecdh_pubkey);
817   enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
818   // Derived key K = H(eB)
819   GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
820                                                         &handle->ticket.audience,
821                                                         &new_key_hash));
822   create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
823   enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
824                                               size + attrs_str_len,
825                                               &skey, &iv,
826                                               enc_keyinfo);
827   *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
828                            enc_size);
829   GNUNET_memcpy (*result,
830                  &ecdh_pubkey,
831                  sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
832   GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
833                  enc_keyinfo,
834                  enc_size);
835   GNUNET_free (enc_keyinfo);
836   return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
837 }
838
839
840
841 static void
842 issue_ticket_after_abe_bootstrap (void *cls,
843                                   struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
844 {
845   struct TicketIssueHandle *ih = cls;
846   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
847   struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
848   struct GNUNET_GNSRECORD_Data code_record[1];
849   struct GNUNET_CRYPTO_AbeKey *rp_key;
850   char *code_record_data;
851   char **attrs;
852   char *label;
853   int attrs_len;
854   int i;
855   size_t code_record_len;
856
857   //Create new ABE key for RP
858   attrs_len = 0;
859   for (le = ih->attrs->list_head; NULL != le; le = le->next)
860     attrs_len++;
861   attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
862   i = 0;
863   for (le = ih->attrs->list_head; NULL != le; le = le->next) {
864     attrs[i] = (char*) le->attribute->name;
865     i++;
866   }
867   attrs[i] = NULL;
868   rp_key = GNUNET_CRYPTO_cpabe_create_key (abe_key,
869                                            attrs);
870
871   //TODO review this wireformat
872   code_record_len = serialize_abe_keyinfo2 (ih,
873                                             rp_key,
874                                             &ecdhe_privkey,
875                                             &code_record_data);
876   code_record[0].data = code_record_data;
877   code_record[0].data_size = code_record_len;
878   code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
879   code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
880   code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
881
882   label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
883                                                sizeof (uint64_t));
884   //Publish record
885   ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
886                                               &ih->identity,
887                                               label,
888                                               1,
889                                               code_record,
890                                               &store_ticket_issue_cont,
891                                               ih);
892   GNUNET_free (ecdhe_privkey);
893   GNUNET_free (label);
894   GNUNET_free (attrs);
895   GNUNET_free (code_record_data);
896 }
897
898
899 /**
900  * Checks a ticket issue message
901  *
902  * @param cls client sending the message
903  * @param im message of type `struct TicketIssueMessage`
904  * @return #GNUNET_OK if @a im is well-formed
905  */
906 static int
907 check_ticket_issue_message(void *cls,
908                            const struct TicketIssueMessage *im)
909 {
910   uint16_t size;
911
912   size = ntohs (im->header.size);
913   if (size <= sizeof (struct TicketIssueMessage))
914   {
915     GNUNET_break (0);
916     return GNUNET_SYSERR;
917   }
918   return GNUNET_OK;
919 }
920
921
922 /**
923  *
924  * Handler for ticket issue message
925  *
926  * @param cls unused
927  * @param client who sent the message
928  * @param message the message
929  */
930 static void
931 handle_ticket_issue_message (void *cls,
932                              const struct TicketIssueMessage *im)
933 {
934   struct TicketIssueHandle *ih;
935   struct IdpClient *idp = cls;
936   size_t attrs_len;
937
938   ih = GNUNET_new (struct TicketIssueHandle);
939   attrs_len = ntohs (im->attr_len);
940   ih->attrs = attribute_list_deserialize ((char*)&im[1], attrs_len);
941   ih->r_id = ntohl (im->id);
942   ih->client = idp;
943   ih->identity = im->identity;
944   GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
945                                       &ih->ticket.identity);
946   ih->ticket.audience = im->rp;
947   ih->ticket.rnd =
948     GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
949                               UINT64_MAX);
950   bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih);
951   GNUNET_SERVICE_client_continue (idp->client);
952
953 }
954
955
956
957 static void
958 cleanup_as_handle (struct AttributeStoreHandle *handle)
959 {
960   if (NULL != handle->attribute)
961     GNUNET_free (handle->attribute);
962   if (NULL != handle->abe_key)
963     GNUNET_free (handle->abe_key);
964   GNUNET_free (handle);
965 }
966
967 /**
968  * Checks a ticket consume message
969  *
970  * @param cls client sending the message
971  * @param im message of type `struct ConsumeTicketMessage`
972  * @return #GNUNET_OK if @a im is well-formed
973  */
974 static int
975 check_consume_ticket_message(void *cls,
976                              const struct ConsumeTicketMessage *cm)
977 {
978   uint16_t size;
979
980   size = ntohs (cm->header.size);
981   if (size <= sizeof (struct ConsumeTicketMessage))
982   {
983     GNUNET_break (0);
984     return GNUNET_SYSERR;
985   }
986   return GNUNET_OK;
987 }
988
989 static void
990 process_parallel_lookup2 (void *cls, uint32_t rd_count,
991                           const struct GNUNET_GNSRECORD_Data *rd)
992 {
993   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
994               "Parallel lookup finished (count=%u)\n", rd_count);
995   struct ParallelLookup *parallel_lookup = cls;
996   struct ConsumeTicketHandle *handle = parallel_lookup->handle;
997   struct ConsumeTicketResultMessage *crm;
998   struct GNUNET_MQ_Envelope *env;
999   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *attr_le;
1000   char *data;
1001   char *data_tmp;
1002   size_t attr_len;
1003   size_t attrs_len;
1004
1005   GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1006                                handle->parallel_lookups_tail,
1007                                parallel_lookup);
1008   GNUNET_free (parallel_lookup->label);
1009   GNUNET_free (parallel_lookup);
1010   if (1 != rd_count)
1011     GNUNET_break(0);//TODO
1012   if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1013   {
1014     attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
1015                                             rd->data_size,
1016                                             handle->key,
1017                                             (void**)&data);
1018     attr_le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
1019     attr_le->attribute = attribute_deserialize (data,
1020                                                 attr_len);
1021     GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
1022                                  handle->attrs->list_tail,
1023                                  attr_le);
1024     GNUNET_free (data);
1025   }
1026   if (NULL != handle->parallel_lookups_head)
1027     return; //Wait for more
1028   /* Else we are done */
1029
1030   /* Store ticket in DB */
1031   if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1032                                                &handle->ticket))
1033   {
1034     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1035                 "Unable to store ticket after consume\n");
1036     GNUNET_break (0);
1037   }
1038   
1039   GNUNET_SCHEDULER_cancel (handle->kill_task);
1040   attrs_len = attribute_list_serialize_get_size (handle->attrs);
1041   env = GNUNET_MQ_msg_extra (crm,
1042                              attrs_len,
1043                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
1044   crm->id = htonl (handle->r_id);
1045   crm->attrs_len = htons (attrs_len);
1046   crm->identity = handle->ticket.identity;
1047   data_tmp = (char *) &crm[1];
1048   attribute_list_serialize (handle->attrs,
1049                             data_tmp);
1050   GNUNET_MQ_send (handle->client->mq, env);
1051 }
1052
1053 void
1054 abort_parallel_lookups2 (void *cls)
1055 {
1056   struct ConsumeTicketHandle *handle = cls;
1057   struct ParallelLookup *lu;
1058   struct ParallelLookup *tmp;
1059   struct AttributeResultMessage *arm;
1060   struct GNUNET_MQ_Envelope *env;
1061
1062   for (lu = handle->parallel_lookups_head;
1063        NULL != lu;) {
1064     GNUNET_GNS_lookup_cancel (lu->lookup_request);
1065     GNUNET_free (lu->label);
1066     tmp = lu->next;
1067     GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1068                                  handle->parallel_lookups_tail,
1069                                  lu);
1070     GNUNET_free (lu);
1071     lu = tmp;
1072   }
1073   env = GNUNET_MQ_msg (arm,
1074                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1075   arm->id = htonl (handle->r_id);
1076   arm->attr_len = htons (0);
1077   GNUNET_MQ_send (handle->client->mq, env);
1078
1079 }
1080
1081 static void
1082 cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
1083 {
1084   if (NULL != handle->key)
1085     GNUNET_free (handle->key);
1086   GNUNET_free (handle);
1087 }
1088
1089
1090 static void
1091 process_consume_abe_key (void *cls, uint32_t rd_count,
1092                          const struct GNUNET_GNSRECORD_Data *rd)
1093 {
1094   struct ConsumeTicketHandle *handle = cls;
1095   struct GNUNET_HashCode new_key_hash;
1096   struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1097   struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1098   struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1099   struct ParallelLookup *parallel_lookup;
1100   size_t size;
1101   char *buf;
1102   char *scope;
1103   char *lookup_query;
1104
1105   handle->lookup_request = NULL;
1106   if (1 != rd_count)
1107   {
1108     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1109                 "Number of keys %d != 1.",
1110                 rd_count);
1111     cleanup_consume_ticket_handle (handle);
1112     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1113     return;
1114   }
1115
1116   //Decrypt
1117   ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1118
1119   buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1120
1121   //Calculate symmetric key from ecdh parameters
1122   GNUNET_assert (GNUNET_OK == 
1123                  GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
1124                                            ecdh_key,
1125                                            &new_key_hash));
1126   create_sym_key_from_ecdh (&new_key_hash,
1127                             &enc_key,
1128                             &enc_iv);
1129   size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1130                                           rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1131                                           &enc_key,
1132                                           &enc_iv,
1133                                           buf);
1134
1135   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1136               "Decrypted bytes: %zd Expected bytes: %zd\n",
1137               size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1138
1139   scopes = GNUNET_strdup (buf);
1140   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1141               "Scopes %s\n", scopes);
1142   handle->key = GNUNET_CRYPTO_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1143                                                      rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1144                                                      - strlen (scopes) - 1);
1145
1146   for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1147   {
1148     GNUNET_asprintf (&lookup_query,
1149                      "%s.gnu",
1150                      scope);
1151     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1152                 "Looking up %s\n", lookup_query);
1153     parallel_lookup = GNUNET_new (struct ParallelLookup);
1154     parallel_lookup->handle = handle;
1155     parallel_lookup->label = GNUNET_strdup (scope);
1156     parallel_lookup->lookup_request
1157       = GNUNET_GNS_lookup (gns_handle,
1158                            lookup_query,
1159                            &handle->ticket.identity,
1160                            GNUNET_GNSRECORD_TYPE_ID_ATTR,
1161                            GNUNET_GNS_LO_LOCAL_MASTER,
1162                            &process_parallel_lookup2,
1163                            parallel_lookup);
1164     GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1165                                  handle->parallel_lookups_tail,
1166                                  parallel_lookup);
1167     GNUNET_free (lookup_query);
1168   }
1169   handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1170                                                     &abort_parallel_lookups2,
1171                                                     handle);
1172 }
1173
1174
1175 /**
1176  *
1177  * Handler for ticket issue message
1178  *
1179  * @param cls unused
1180  * @param client who sent the message
1181  * @param message the message
1182  */
1183 static void
1184 handle_consume_ticket_message (void *cls,
1185                                const struct ConsumeTicketMessage *cm)
1186 {
1187   struct ConsumeTicketHandle *ch;
1188   struct IdpClient *idp = cls;
1189   char* lookup_query;
1190   char* rnd_label;
1191
1192   ch = GNUNET_new (struct ConsumeTicketHandle);
1193   ch->r_id = ntohl (cm->id);
1194   ch->client = idp;
1195   ch->identity = cm->identity;
1196   ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
1197   GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
1198                                       &ch->identity_pub);
1199   ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
1200   rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
1201                                                    sizeof (uint64_t));
1202   GNUNET_asprintf (&lookup_query,
1203                    "%s.gnu",
1204                    rnd_label);
1205   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1206               "Looking for ABE key under %s\n", lookup_query);
1207
1208   ch->lookup_request
1209     = GNUNET_GNS_lookup (gns_handle,
1210                          lookup_query,
1211                          &ch->ticket.identity,
1212                          GNUNET_GNSRECORD_TYPE_ABE_KEY,
1213                          GNUNET_GNS_LO_LOCAL_MASTER,
1214                          &process_consume_abe_key,
1215                          ch);
1216   GNUNET_free (rnd_label);
1217   GNUNET_free (lookup_query);
1218   GNUNET_SERVICE_client_continue (idp->client);
1219 }
1220
1221 void
1222 attr_store_cont (void *cls,
1223                  int32_t success,
1224                  const char *emsg)
1225 {
1226   struct AttributeStoreHandle *as_handle = cls;
1227   struct GNUNET_MQ_Envelope *env;
1228   struct AttributeStoreResponseMessage *acr_msg;
1229
1230   if (GNUNET_SYSERR == success)
1231   {
1232     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1233                 "Failed to store attribute %s\n",
1234                 emsg);
1235     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1236     return;
1237   }
1238
1239   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1240               "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1241   env = GNUNET_MQ_msg (acr_msg,
1242                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
1243   acr_msg->id = htonl (as_handle->r_id);
1244   acr_msg->op_result = htonl (GNUNET_OK);
1245   GNUNET_MQ_send (as_handle->client->mq,
1246                   env);
1247   cleanup_as_handle (as_handle);
1248 }
1249
1250 static void
1251 attr_store_task (void *cls)
1252 {
1253   struct AttributeStoreHandle *as_handle = cls;
1254   struct GNUNET_GNSRECORD_Data rd[1];
1255   char* buf;
1256   size_t buf_size;
1257
1258   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1259               "Storing attribute\n");
1260   buf_size = attribute_serialize_get_size (as_handle->attribute);
1261   buf = GNUNET_malloc (buf_size);
1262
1263   attribute_serialize (as_handle->attribute,
1264                        buf);
1265
1266   /**
1267    * Encrypt the attribute value and store in namestore
1268    */
1269   rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1270                                                  buf_size,
1271                                                  as_handle->attribute->name, //Policy
1272                                                  as_handle->abe_key,
1273                                                  (void**)&rd[0].data);
1274   GNUNET_free (buf);
1275   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1276   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1277   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1278   as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1279                                                      &as_handle->identity,
1280                                                      as_handle->attribute->name,
1281                                                      1,
1282                                                      rd,
1283                                                      &attr_store_cont,
1284                                                      as_handle);
1285   GNUNET_free ((void*)rd[0].data);
1286
1287 }
1288
1289
1290 static void
1291 store_after_abe_bootstrap (void *cls,
1292                            struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1293 {
1294   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1295               "Finished ABE bootstrap\n");
1296   struct AttributeStoreHandle *ash = cls;
1297   ash->abe_key = abe_key;
1298   GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1299 }
1300
1301 /**
1302  * Checks a store message
1303  *
1304  * @param cls client sending the message
1305  * @param sam message of type `struct AttributeStoreMessage`
1306  * @return #GNUNET_OK if @a im is well-formed
1307  */
1308 static int
1309 check_attribute_store_message(void *cls,
1310                               const struct AttributeStoreMessage *sam)
1311 {
1312   uint16_t size;
1313
1314   size = ntohs (sam->header.size);
1315   if (size <= sizeof (struct AttributeStoreMessage))
1316   {
1317     GNUNET_break (0);
1318     return GNUNET_SYSERR;
1319   }
1320   return GNUNET_OK;
1321 }
1322
1323
1324 /**
1325  *
1326  * Handler for store message
1327  *
1328  * @param cls unused
1329  * @param client who sent the message
1330  * @param message the message
1331  */
1332 static void
1333 handle_attribute_store_message (void *cls,
1334                                 const struct AttributeStoreMessage *sam)
1335 {
1336   struct AttributeStoreHandle *as_handle;
1337   struct IdpClient *idp = cls;
1338   size_t data_len;
1339   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1340               "Received ATTRIBUTE_STORE message\n");
1341
1342   data_len = ntohs (sam->attr_len);
1343
1344   as_handle = GNUNET_new (struct AttributeStoreHandle);
1345   as_handle->attribute = attribute_deserialize ((char*)&sam[1],
1346                                                 data_len);
1347
1348   as_handle->r_id = ntohl (sam->id);
1349   as_handle->identity = sam->identity;
1350   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1351                                       &as_handle->identity_pkey);
1352
1353   GNUNET_SERVICE_client_continue (idp->client);
1354   as_handle->client = idp;
1355   bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle);
1356 }
1357
1358 static void
1359 cleanup_iter_handle (struct AttributeIterator *ai)
1360 {
1361   if (NULL != ai->abe_key)
1362     GNUNET_free (ai->abe_key);
1363   GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
1364                                ai->client->op_tail,
1365                                ai);
1366   GNUNET_free (ai);
1367 }
1368
1369 static void
1370 attr_iter_error (void *cls)
1371 {
1372   //struct AttributeIterator *ai = cls;
1373   //TODO
1374   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1375               "Failed to iterate over attributes\n");
1376   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1377 }
1378
1379 static void
1380 attr_iter_finished (void *cls)
1381 {
1382   struct AttributeIterator *ai = cls;
1383   struct GNUNET_MQ_Envelope *env;
1384   struct AttributeResultMessage *arm;
1385
1386   env = GNUNET_MQ_msg (arm,
1387                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1388   arm->id = htonl (ai->request_id);
1389   arm->attr_len = htons (0);
1390   GNUNET_MQ_send (ai->client->mq, env);
1391   cleanup_iter_handle (ai);
1392 }
1393
1394 static void
1395 attr_iter_cb (void *cls,
1396               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1397               const char *label,
1398               unsigned int rd_count,
1399               const struct GNUNET_GNSRECORD_Data *rd)
1400 {
1401   struct AttributeIterator *ai = cls;
1402   struct AttributeResultMessage *arm;
1403   struct GNUNET_CRYPTO_AbeKey *key;
1404   struct GNUNET_MQ_Envelope *env;
1405   ssize_t msg_extra_len;
1406   char* attr_ser;
1407   char* attrs[2];
1408   char* data_tmp;
1409
1410   if (rd_count != 1)
1411   {
1412     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1413     return;
1414   }
1415
1416   if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
1417     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1418     return;
1419   }
1420   attrs[0] = (char*)label;
1421   attrs[1] = 0;
1422   key = GNUNET_CRYPTO_cpabe_create_key (ai->abe_key,
1423                                         attrs);
1424   msg_extra_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
1425                                                rd->data_size,
1426                                                key,
1427                                                (void**)&attr_ser);
1428   GNUNET_CRYPTO_cpabe_delete_key (key);
1429   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1430               "Found attribute: %s\n", label);
1431   env = GNUNET_MQ_msg_extra (arm,
1432                              msg_extra_len,
1433                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1434   arm->id = htonl (ai->request_id);
1435   arm->attr_len = htons (msg_extra_len);
1436   GNUNET_CRYPTO_ecdsa_key_get_public (zone,
1437                                       &arm->identity);
1438   data_tmp = (char *) &arm[1];
1439   GNUNET_memcpy (data_tmp,
1440                  attr_ser,
1441                  msg_extra_len);
1442   GNUNET_MQ_send (ai->client->mq, env);
1443   GNUNET_free (attr_ser);
1444 }
1445
1446
1447 void
1448 iterate_after_abe_bootstrap (void *cls,
1449                              struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1450 {
1451   struct AttributeIterator *ai = cls;
1452   ai->abe_key = abe_key;
1453   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1454                                                      &ai->identity,
1455                                                      &attr_iter_error,
1456                                                      ai,
1457                                                      &attr_iter_cb,
1458                                                      ai,
1459                                                      &attr_iter_finished,
1460                                                      ai);
1461 }
1462
1463
1464 /**
1465  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_START message
1466  *
1467  * @param cls the client sending the message
1468  * @param zis_msg message from the client
1469  */
1470 static void
1471 handle_iteration_start (void *cls,
1472                         const struct AttributeIterationStartMessage *ais_msg)
1473 {
1474   struct IdpClient *idp = cls;
1475   struct AttributeIterator *ai;
1476
1477   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1478               "Received ATTRIBUTE_ITERATION_START message\n");
1479   ai = GNUNET_new (struct AttributeIterator);
1480   ai->request_id = ntohl (ais_msg->id);
1481   ai->client = idp;
1482   ai->identity = ais_msg->identity;
1483
1484   GNUNET_CONTAINER_DLL_insert (idp->op_head,
1485                                idp->op_tail,
1486                                ai);
1487   bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai);
1488   GNUNET_SERVICE_client_continue (idp->client);
1489 }
1490
1491
1492 /**
1493  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_STOP message
1494  *
1495  * @param cls the client sending the message
1496  * @param ais_msg message from the client
1497  */
1498 static void
1499 handle_iteration_stop (void *cls,
1500                        const struct AttributeIterationStopMessage *ais_msg)
1501 {
1502   struct IdpClient *idp = cls;
1503   struct AttributeIterator *ai;
1504   uint32_t rid;
1505
1506   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1507               "Received `%s' message\n",
1508               "ATTRIBUTE_ITERATION_STOP");
1509   rid = ntohl (ais_msg->id);
1510   for (ai = idp->op_head; NULL != ai; ai = ai->next)
1511     if (ai->request_id == rid)
1512       break;
1513   if (NULL == ai)
1514   {
1515     GNUNET_break (0);
1516     GNUNET_SERVICE_client_drop (idp->client);
1517     return;
1518   }
1519   GNUNET_CONTAINER_DLL_remove (idp->op_head,
1520                                idp->op_tail,
1521                                ai);
1522   GNUNET_free (ai);
1523   GNUNET_SERVICE_client_continue (idp->client);
1524 }
1525
1526
1527 /**
1528  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT message
1529  *
1530  * @param cls the client sending the message
1531  * @param message message from the client
1532  */
1533 static void
1534 handle_iteration_next (void *cls,
1535                        const struct AttributeIterationNextMessage *ais_msg)
1536 {
1537   struct IdpClient *idp = cls;
1538   struct AttributeIterator *ai;
1539   uint32_t rid;
1540
1541   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1542               "Received ATTRIBUTE_ITERATION_NEXT message\n");
1543   rid = ntohl (ais_msg->id);
1544   for (ai = idp->op_head; NULL != ai; ai = ai->next)
1545     if (ai->request_id == rid)
1546       break;
1547   if (NULL == ai)
1548   {
1549     GNUNET_break (0);
1550     GNUNET_SERVICE_client_drop (idp->client);
1551     return;
1552   }
1553   GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1554   GNUNET_SERVICE_client_continue (idp->client);
1555 }
1556
1557 /**
1558  * Ticket iteration processor result
1559  */
1560 enum ZoneIterationResult
1561 {
1562   /**
1563    * Iteration start.
1564    */
1565   IT_START = 0,
1566
1567   /**
1568    * Found tickets,
1569    * Continue to iterate with next iteration_next call
1570    */
1571   IT_SUCCESS_MORE_AVAILABLE = 1,
1572
1573   /**
1574    * Iteration complete
1575    */
1576   IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
1577 };
1578
1579
1580 /**
1581  * Context for ticket iteration
1582  */
1583 struct TicketIterationProcResult
1584 {
1585   /**
1586    * The ticket iteration handle
1587    */
1588   struct TicketIteration *ti;
1589
1590   /**
1591    * Iteration result: iteration done?
1592    * #IT_SUCCESS_MORE_AVAILABLE:  if there may be more results overall but
1593    * we got one for now and have sent it to the client
1594    * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
1595    * #IT_START: if we are still trying to find a result.
1596    */
1597   int res_iteration_finished;
1598
1599 };
1600
1601
1602
1603 /**
1604  * Process ticket from database
1605  *
1606  * @param cls struct TicketIterationProcResult
1607  * @param ticket the ticket
1608  * @param attrs the attributes
1609  */
1610 static void
1611 ticket_iterate_proc (void *cls,
1612                      const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
1613 {
1614   struct TicketIterationProcResult *proc = cls;
1615
1616   if (NULL == ticket)
1617   {
1618     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1619                 "Iteration done\n");
1620     proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
1621     return;
1622   }
1623   proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
1624   send_ticket_result (proc->ti->client,
1625                       proc->ti->r_id,
1626                       ticket);
1627
1628 }
1629
1630 /**
1631  * Perform ticket iteration step
1632  *
1633  * @param ti ticket iterator to process
1634  */
1635 static void
1636 run_ticket_iteration_round (struct TicketIteration *ti)
1637 {
1638   struct TicketIterationProcResult proc;
1639   struct GNUNET_MQ_Envelope *env;
1640   struct TicketResultMessage *trm;
1641   int ret;
1642
1643   memset (&proc, 0, sizeof (proc));
1644   proc.ti = ti;
1645   proc.res_iteration_finished = IT_START;
1646   while (IT_START == proc.res_iteration_finished)
1647   {
1648     if (GNUNET_SYSERR ==
1649         (ret = TKT_database->iterate_tickets (TKT_database->cls,
1650                                               &ti->identity,
1651                                               ti->is_audience,
1652                                               ti->offset,
1653                                               &ticket_iterate_proc,
1654                                               &proc)))
1655     {
1656       GNUNET_break (0);
1657       break;
1658     }
1659     if (GNUNET_NO == ret)
1660       proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
1661     ti->offset++;
1662   }
1663   if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
1664   {
1665     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1666                 "More results available\n");
1667     return; /* more later */
1668   }
1669   /* send empty response to indicate end of list */
1670   env = GNUNET_MQ_msg (trm,
1671                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
1672   trm->id = htonl (ti->r_id);
1673   GNUNET_MQ_send (ti->client->mq,
1674                   env);
1675   GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
1676                                ti->client->ticket_iter_tail,
1677                                ti);
1678   GNUNET_free (ti);
1679 }
1680
1681 /**
1682  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START message
1683  *
1684  * @param cls the client sending the message
1685  * @param tis_msg message from the client
1686  */
1687 static void
1688 handle_ticket_iteration_start (void *cls,
1689                                const struct TicketIterationStartMessage *tis_msg)
1690 {
1691   struct IdpClient *client = cls;
1692   struct TicketIteration *ti;
1693
1694   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1695               "Received TICKET_ITERATION_START message\n");
1696   ti = GNUNET_new (struct TicketIteration);
1697   ti->r_id = ntohl (tis_msg->id);
1698   ti->offset = 0;
1699   ti->client = client;
1700   ti->identity = tis_msg->identity;
1701   ti->is_audience = ntohl (tis_msg->is_audience);
1702
1703   GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
1704                                client->ticket_iter_tail,
1705                                ti);
1706   run_ticket_iteration_round (ti);
1707   GNUNET_SERVICE_client_continue (client->client);
1708 }
1709
1710
1711 /**
1712  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP message
1713  *
1714  * @param cls the client sending the message
1715  * @param tis_msg message from the client
1716  */
1717 static void
1718 handle_ticket_iteration_stop (void *cls,
1719                               const struct TicketIterationStopMessage *tis_msg)
1720 {
1721   struct IdpClient *client = cls;
1722   struct TicketIteration *ti;
1723   uint32_t rid;
1724
1725   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1726               "Received `%s' message\n",
1727               "TICKET_ITERATION_STOP");
1728   rid = ntohl (tis_msg->id);
1729   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1730     if (ti->r_id == rid)
1731       break;
1732   if (NULL == ti)
1733   {
1734     GNUNET_break (0);
1735     GNUNET_SERVICE_client_drop (client->client);
1736     return;
1737   }
1738   GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
1739                                client->ticket_iter_tail,
1740                                ti);
1741   GNUNET_free (ti);
1742   GNUNET_SERVICE_client_continue (client->client);
1743 }
1744
1745
1746 /**
1747  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT message
1748  *
1749  * @param cls the client sending the message
1750  * @param message message from the client
1751  */
1752 static void
1753 handle_ticket_iteration_next (void *cls,
1754                               const struct TicketIterationNextMessage *tis_msg)
1755 {
1756   struct IdpClient *client = cls;
1757   struct TicketIteration *ti;
1758   uint32_t rid;
1759
1760   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1761               "Received TICKET_ITERATION_NEXT message\n");
1762   rid = ntohl (tis_msg->id);
1763   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1764     if (ti->r_id == rid)
1765       break;
1766   if (NULL == ti)
1767   {
1768     GNUNET_break (0);
1769     GNUNET_SERVICE_client_drop (client->client);
1770     return;
1771   }
1772   run_ticket_iteration_round (ti);
1773   GNUNET_SERVICE_client_continue (client->client);
1774 }
1775
1776
1777
1778
1779 /**
1780  * Main function that will be run
1781  *
1782  * @param cls closure
1783  * @param args remaining command-line arguments
1784  * @param cfgfile name of the configuration file used (for saving, can be NULL)
1785  * @param c configuration
1786  */
1787 static void
1788 run (void *cls,
1789      const struct GNUNET_CONFIGURATION_Handle *c,
1790      struct GNUNET_SERVICE_Handle *server)
1791 {
1792   char *database;
1793   cfg = c;
1794
1795   stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
1796
1797   //Connect to identity and namestore services
1798   ns_handle = GNUNET_NAMESTORE_connect (cfg);
1799   if (NULL == ns_handle)
1800   {
1801     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
1802   }
1803
1804   gns_handle = GNUNET_GNS_connect (cfg);
1805   if (NULL == gns_handle)
1806   {
1807     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1808   }
1809   credential_handle = GNUNET_CREDENTIAL_connect (cfg);
1810   if (NULL == credential_handle)
1811   {
1812     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
1813   }
1814   identity_handle = GNUNET_IDENTITY_connect (cfg,
1815                                              NULL,
1816                                              NULL);
1817
1818   /* Loading DB plugin */
1819   if (GNUNET_OK !=
1820       GNUNET_CONFIGURATION_get_value_string (cfg,
1821                                              "identity-provider",
1822                                              "database",
1823                                              &database))
1824     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1825                 "No database backend configured\n");
1826   GNUNET_asprintf (&db_lib_name,
1827                    "libgnunet_plugin_identity_provider_%s",
1828                    database);
1829   TKT_database = GNUNET_PLUGIN_load (db_lib_name,
1830                                      (void *) cfg);
1831   GNUNET_free (database);
1832   if (NULL == TKT_database)
1833   {
1834     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1835                 "Could not load database backend `%s'\n",
1836                 db_lib_name);
1837     GNUNET_SCHEDULER_shutdown ();
1838     return;
1839   }
1840
1841   if (GNUNET_OK ==
1842       GNUNET_CONFIGURATION_get_value_time (cfg,
1843                                            "identity-provider",
1844                                            "TOKEN_EXPIRATION_INTERVAL",
1845                                            &token_expiration_interval))
1846   {
1847     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1848                 "Time window for zone iteration: %s\n",
1849                 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
1850                                                         GNUNET_YES));
1851   } else {
1852     token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
1853   }
1854
1855   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1856 }
1857
1858 /**
1859  * Called whenever a client is disconnected.
1860  *
1861  * @param cls closure
1862  * @param client identification of the client
1863  * @param app_ctx @a client
1864  */
1865 static void
1866 client_disconnect_cb (void *cls,
1867                       struct GNUNET_SERVICE_Client *client,
1868                       void *app_ctx)
1869 {
1870   struct IdpClient *idp = app_ctx;
1871   struct AttributeIterator *ai;
1872
1873   //TODO other operations
1874
1875   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1876               "Client %p disconnected\n",
1877               client);
1878
1879   while (NULL != (ai = idp->op_head))
1880   {
1881     GNUNET_CONTAINER_DLL_remove (idp->op_head,
1882                                  idp->op_tail,
1883                                  ai);
1884     GNUNET_free (ai);
1885   }
1886   GNUNET_free (idp);
1887 }
1888
1889
1890 /**
1891  * Add a client to our list of active clients.
1892  *
1893  * @param cls NULL
1894  * @param client client to add
1895  * @param mq message queue for @a client
1896  * @return internal namestore client structure for this client
1897  */
1898 static void *
1899 client_connect_cb (void *cls,
1900                    struct GNUNET_SERVICE_Client *client,
1901                    struct GNUNET_MQ_Handle *mq)
1902 {
1903   struct IdpClient *idp;
1904   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1905               "Client %p connected\n",
1906               client);
1907   idp = GNUNET_new (struct IdpClient);
1908   idp->client = client;
1909   idp->mq = mq;
1910   return idp;
1911 }
1912
1913
1914
1915 /**
1916  * Define "main" method using service macro.
1917  */
1918 GNUNET_SERVICE_MAIN
1919 ("identity-provider",
1920  GNUNET_SERVICE_OPTION_NONE,
1921  &run,
1922  &client_connect_cb,
1923  &client_disconnect_cb,
1924  NULL,
1925  GNUNET_MQ_hd_var_size (attribute_store_message,
1926                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
1927                         struct AttributeStoreMessage,
1928                         NULL),
1929  GNUNET_MQ_hd_fixed_size (iteration_start, 
1930                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
1931                           struct AttributeIterationStartMessage,
1932                           NULL),
1933  GNUNET_MQ_hd_fixed_size (iteration_next, 
1934                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
1935                           struct AttributeIterationNextMessage,
1936                           NULL),
1937  GNUNET_MQ_hd_fixed_size (iteration_stop, 
1938                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
1939                           struct AttributeIterationStopMessage,
1940                           NULL),
1941  GNUNET_MQ_hd_var_size (ticket_issue_message,
1942                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE,
1943                         struct TicketIssueMessage,
1944                         NULL),
1945  GNUNET_MQ_hd_var_size (consume_ticket_message,
1946                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
1947                         struct ConsumeTicketMessage,
1948                         NULL),
1949  GNUNET_MQ_hd_fixed_size (ticket_iteration_start, 
1950                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
1951                           struct TicketIterationStartMessage,
1952                           NULL),
1953  GNUNET_MQ_hd_fixed_size (ticket_iteration_next, 
1954                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
1955                           struct TicketIterationNextMessage,
1956                           NULL),
1957  GNUNET_MQ_hd_fixed_size (ticket_iteration_stop, 
1958                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
1959                           struct TicketIterationStopMessage,
1960                           NULL),
1961
1962  GNUNET_MQ_handler_end());
1963  /* end of gnunet-service-identity-provider.c */