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