-add ticket iteration
[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_DEBUG,
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_DEBUG, "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_DEBUG, "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_DEBUG,
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_DEBUG,
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   struct GNUNET_IDENTITY_PROVIDER_Ticket2 *ticket_buf;
1774
1775   /* store ticket in DB */
1776   if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1777                                                ticket,
1778                                                attrs))
1779   {
1780     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1781                 "Unable to store ticket after issue\n");
1782     GNUNET_break (0);
1783   }
1784
1785   env = GNUNET_MQ_msg_extra (irm,
1786                              sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket2),
1787                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
1788   ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket2 *)&irm[1];
1789   *ticket_buf = *ticket;
1790   irm->id = htonl (r_id);
1791   GNUNET_MQ_send (client->mq,
1792                   env);
1793 }
1794
1795 static void
1796 store_ticket_issue_cont (void *cls,
1797                          int32_t success,
1798                          const char *emsg)
1799 {
1800   struct TicketIssueHandle *handle = cls;
1801
1802   handle->ns_qe = NULL;
1803   if (GNUNET_SYSERR == success)
1804   {
1805     cleanup_ticket_issue_handle (handle);
1806     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1807                 "Unknown Error\n");
1808     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1809     return;
1810   }
1811   send_ticket_result (handle->client,
1812                       handle->r_id,
1813                       &handle->ticket,
1814                       handle->attrs);
1815   cleanup_ticket_issue_handle (handle);
1816 }
1817
1818
1819
1820 int
1821 serialize_abe_keyinfo2 (const struct TicketIssueHandle *handle,
1822                         const struct GNUNET_CRYPTO_AbeKey *rp_key,
1823                         struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
1824                         char **result)
1825 {
1826   struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
1827   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1828   char *enc_keyinfo;
1829   char *serialized_key;
1830   char *buf;
1831   char *write_ptr;
1832   char attrs_str_len;
1833   ssize_t size;
1834
1835   struct GNUNET_CRYPTO_SymmetricSessionKey skey;
1836   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1837   struct GNUNET_HashCode new_key_hash;
1838   ssize_t enc_size;
1839
1840   size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key,
1841                                             (void**)&serialized_key);
1842   attrs_str_len = 0;
1843   for (le = handle->attrs->list_head; NULL != le; le = le->next) {
1844     attrs_str_len += strlen (le->attribute->name) + 1;
1845   }
1846   buf = GNUNET_malloc (attrs_str_len + size);
1847   write_ptr = buf;
1848   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1849               "Writing attributes\n");
1850   for (le = handle->attrs->list_head; NULL != le; le = le->next) {
1851     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1852                 "%s\n", le->attribute->name);
1853
1854
1855     GNUNET_memcpy (write_ptr,
1856                    le->attribute->name,
1857                    strlen (le->attribute->name));
1858     write_ptr[strlen (le->attribute->name)] = ',';
1859     write_ptr += strlen (le->attribute->name) + 1;
1860   }
1861   write_ptr--;
1862   write_ptr[0] = '\0'; //replace last , with a 0-terminator
1863   write_ptr++;
1864   GNUNET_memcpy (write_ptr,
1865                  serialized_key,
1866                  size);
1867   // ECDH keypair E = eG
1868   *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
1869   GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
1870                                       &ecdh_pubkey);
1871   enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
1872   // Derived key K = H(eB)
1873   GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
1874                                                         &handle->ticket.audience,
1875                                                         &new_key_hash));
1876   create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
1877   enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
1878                                               size + attrs_str_len,
1879                                               &skey, &iv,
1880                                               enc_keyinfo);
1881   *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
1882                            enc_size);
1883   GNUNET_memcpy (*result,
1884                  &ecdh_pubkey,
1885                  sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1886   GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1887                  enc_keyinfo,
1888                  enc_size);
1889   GNUNET_free (enc_keyinfo);
1890   return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
1891 }
1892
1893
1894
1895 static void
1896 issue_ticket_after_abe_bootstrap (void *cls,
1897                                   struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1898 {
1899   struct TicketIssueHandle *ih = cls;
1900   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1901   struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
1902   struct GNUNET_GNSRECORD_Data code_record[1];
1903   struct GNUNET_CRYPTO_AbeKey *rp_key;
1904   char *code_record_data;
1905   char **attrs;
1906   char *label;
1907   int attrs_len;
1908   int i;
1909   size_t code_record_len;
1910
1911   //Create new ABE key for RP
1912   attrs_len = 0;
1913   for (le = ih->attrs->list_head; NULL != le; le = le->next)
1914     attrs_len++;
1915   attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1916   i = 0;
1917   for (le = ih->attrs->list_head; NULL != le; le = le->next) {
1918     attrs[i] = (char*) le->attribute->name;
1919     i++;
1920   }
1921   attrs[i] = NULL;
1922   rp_key = GNUNET_CRYPTO_cpabe_create_key (abe_key,
1923                                            attrs);
1924
1925   //TODO review this wireformat
1926   code_record_len = serialize_abe_keyinfo2 (ih,
1927                                             rp_key,
1928                                             &ecdhe_privkey,
1929                                             &code_record_data);
1930   code_record[0].data = code_record_data;
1931   code_record[0].data_size = code_record_len;
1932   code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1933   code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1934   code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1935
1936   label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
1937                                                sizeof (uint64_t));
1938   //Publish record
1939   ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1940                                               &ih->identity,
1941                                               label,
1942                                               1,
1943                                               code_record,
1944                                               &store_ticket_issue_cont,
1945                                               ih);
1946   GNUNET_free (ecdhe_privkey);
1947   GNUNET_free (label);
1948   GNUNET_free (attrs);
1949   GNUNET_free (code_record_data);
1950 }
1951
1952
1953 /**
1954  * Checks a ticket issue message
1955  *
1956  * @param cls client sending the message
1957  * @param im message of type `struct TicketIssueMessage`
1958  * @return #GNUNET_OK if @a im is well-formed
1959  */
1960 static int
1961 check_ticket_issue_message(void *cls,
1962                            const struct TicketIssueMessage *im)
1963 {
1964   uint16_t size;
1965
1966   size = ntohs (im->header.size);
1967   if (size <= sizeof (struct TicketIssueMessage))
1968   {
1969     GNUNET_break (0);
1970     return GNUNET_SYSERR;
1971   }
1972   return GNUNET_OK;
1973 }
1974
1975
1976 /**
1977  *
1978  * Handler for ticket issue message
1979  *
1980  * @param cls unused
1981  * @param client who sent the message
1982  * @param message the message
1983  */
1984 static void
1985 handle_ticket_issue_message (void *cls,
1986                              const struct TicketIssueMessage *im)
1987 {
1988   struct TicketIssueHandle *ih;
1989   struct IdpClient *idp = cls;
1990   size_t attrs_len;
1991
1992   ih = GNUNET_new (struct TicketIssueHandle);
1993   attrs_len = ntohs (im->attr_len);
1994   ih->attrs = attribute_list_deserialize ((char*)&im[1], attrs_len);
1995   ih->r_id = ntohl (im->id);
1996   ih->client = idp;
1997   ih->identity = im->identity;
1998   GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
1999                                       &ih->ticket.identity);
2000   ih->ticket.audience = im->rp;
2001   ih->ticket.rnd =
2002     GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
2003                               UINT64_MAX);
2004   bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih);
2005   GNUNET_SERVICE_client_continue (idp->client);
2006
2007 }
2008
2009
2010
2011 static void
2012 cleanup_as_handle (struct AttributeStoreHandle *handle)
2013 {
2014   if (NULL != handle->attribute)
2015     GNUNET_free (handle->attribute);
2016   if (NULL != handle->abe_key)
2017     GNUNET_free (handle->abe_key);
2018   GNUNET_free (handle);
2019 }
2020
2021 /**
2022  * Checks a ticket consume message
2023  *
2024  * @param cls client sending the message
2025  * @param im message of type `struct ConsumeTicketMessage`
2026  * @return #GNUNET_OK if @a im is well-formed
2027  */
2028 static int
2029 check_consume_ticket_message(void *cls,
2030                              const struct ConsumeTicketMessage *cm)
2031 {
2032   uint16_t size;
2033
2034   size = ntohs (cm->header.size);
2035   if (size <= sizeof (struct ConsumeTicketMessage))
2036   {
2037     GNUNET_break (0);
2038     return GNUNET_SYSERR;
2039   }
2040   return GNUNET_OK;
2041 }
2042
2043 static void
2044 process_parallel_lookup2 (void *cls, uint32_t rd_count,
2045                           const struct GNUNET_GNSRECORD_Data *rd)
2046 {
2047   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2048               "Parallel lookup finished (count=%u)\n", rd_count);
2049   struct ParallelLookup2 *parallel_lookup = cls;
2050   struct ConsumeTicketHandle *handle = parallel_lookup->handle;
2051   struct ConsumeTicketResultMessage *crm;
2052   struct GNUNET_MQ_Envelope *env;
2053   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *attr_le;
2054   char *data;
2055   char *data_tmp;
2056   size_t attr_len;
2057   size_t attrs_len;
2058
2059   GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
2060                                handle->parallel_lookups_tail,
2061                                parallel_lookup);
2062   GNUNET_free (parallel_lookup->label);
2063   GNUNET_free (parallel_lookup);
2064   if (1 != rd_count)
2065     GNUNET_break(0);//TODO
2066   if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
2067   {
2068     attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
2069                                             rd->data_size,
2070                                             handle->key,
2071                                             (void**)&data);
2072     attr_le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
2073     attr_le->attribute = attribute_deserialize (data,
2074                                                 attr_len);
2075     GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
2076                                  handle->attrs->list_tail,
2077                                  attr_le);
2078     GNUNET_free (data);
2079   }
2080   if (NULL != handle->parallel_lookups_head)
2081     return; //Wait for more
2082   /* Else we are done */
2083
2084   /* Store ticket in DB */
2085   if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
2086                                                &handle->ticket,
2087                                                handle->attrs))
2088   {
2089     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2090                 "Unable to store ticket after consume\n");
2091     GNUNET_break (0);
2092   }
2093   
2094   GNUNET_SCHEDULER_cancel (handle->kill_task);
2095   attrs_len = attribute_list_serialize_get_size (handle->attrs);
2096   env = GNUNET_MQ_msg_extra (crm,
2097                              attrs_len,
2098                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
2099   crm->id = htonl (handle->r_id);
2100   crm->attrs_len = htons (attrs_len);
2101   crm->identity = handle->ticket.identity;
2102   data_tmp = (char *) &crm[1];
2103   attribute_list_serialize (handle->attrs,
2104                             data_tmp);
2105   GNUNET_MQ_send (handle->client->mq, env);
2106 }
2107
2108 void
2109 abort_parallel_lookups2 (void *cls)
2110 {
2111   struct ConsumeTicketHandle *handle = cls;
2112   struct ParallelLookup2 *lu;
2113   struct ParallelLookup2 *tmp;
2114   struct AttributeResultMessage *arm;
2115   struct GNUNET_MQ_Envelope *env;
2116
2117   for (lu = handle->parallel_lookups_head;
2118        NULL != lu;) {
2119     GNUNET_GNS_lookup_cancel (lu->lookup_request);
2120     GNUNET_free (lu->label);
2121     tmp = lu->next;
2122     GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
2123                                  handle->parallel_lookups_tail,
2124                                  lu);
2125     GNUNET_free (lu);
2126     lu = tmp;
2127   }
2128   env = GNUNET_MQ_msg (arm,
2129                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
2130   arm->id = htonl (handle->r_id);
2131   arm->attr_len = htons (0);
2132   GNUNET_MQ_send (handle->client->mq, env);
2133
2134 }
2135
2136 static void
2137 cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
2138 {
2139   if (NULL != handle->key)
2140     GNUNET_free (handle->key);
2141   GNUNET_free (handle);
2142 }
2143
2144
2145 static void
2146 process_consume_abe_key (void *cls, uint32_t rd_count,
2147                          const struct GNUNET_GNSRECORD_Data *rd)
2148 {
2149   struct ConsumeTicketHandle *handle = cls;
2150   struct GNUNET_HashCode new_key_hash;
2151   struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
2152   struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
2153   struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
2154   struct ParallelLookup2 *parallel_lookup;
2155   size_t size;
2156   char *buf;
2157   char *scope;
2158   char *lookup_query;
2159
2160   handle->lookup_request = NULL;
2161   if (1 != rd_count)
2162   {
2163     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2164                 "Number of keys %d != 1.",
2165                 rd_count);
2166     cleanup_consume_ticket_handle (handle);
2167     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
2168     return;
2169   }
2170
2171   //Decrypt
2172   ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
2173
2174   buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
2175
2176   //Calculate symmetric key from ecdh parameters
2177   GNUNET_assert (GNUNET_OK == 
2178                  GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
2179                                            ecdh_key,
2180                                            &new_key_hash));
2181   create_sym_key_from_ecdh (&new_key_hash,
2182                             &enc_key,
2183                             &enc_iv);
2184   size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
2185                                           rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
2186                                           &enc_key,
2187                                           &enc_iv,
2188                                           buf);
2189
2190   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2191               "Decrypted bytes: %zd Expected bytes: %zd\n",
2192               size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
2193
2194   scopes = GNUNET_strdup (buf);
2195   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2196               "Scopes %s\n", scopes);
2197   handle->key = GNUNET_CRYPTO_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
2198                                                      rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
2199                                                      - strlen (scopes) - 1);
2200
2201   for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
2202   {
2203     GNUNET_asprintf (&lookup_query,
2204                      "%s.gnu",
2205                      scope);
2206     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2207                 "Looking up %s\n", lookup_query);
2208     parallel_lookup = GNUNET_new (struct ParallelLookup2);
2209     parallel_lookup->handle = handle;
2210     parallel_lookup->label = GNUNET_strdup (scope);
2211     parallel_lookup->lookup_request
2212       = GNUNET_GNS_lookup (gns_handle,
2213                            lookup_query,
2214                            &handle->ticket.identity,
2215                            GNUNET_GNSRECORD_TYPE_ID_ATTR,
2216                            GNUNET_GNS_LO_LOCAL_MASTER,
2217                            &process_parallel_lookup2,
2218                            parallel_lookup);
2219     GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
2220                                  handle->parallel_lookups_tail,
2221                                  parallel_lookup);
2222     GNUNET_free (lookup_query);
2223   }
2224   handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
2225                                                     &abort_parallel_lookups2,
2226                                                     handle);
2227 }
2228
2229
2230 /**
2231  *
2232  * Handler for ticket issue message
2233  *
2234  * @param cls unused
2235  * @param client who sent the message
2236  * @param message the message
2237  */
2238 static void
2239 handle_consume_ticket_message (void *cls,
2240                                const struct ConsumeTicketMessage *cm)
2241 {
2242   struct ConsumeTicketHandle *ch;
2243   struct IdpClient *idp = cls;
2244   char* lookup_query;
2245   char* rnd_label;
2246
2247   ch = GNUNET_new (struct ConsumeTicketHandle);
2248   ch->r_id = ntohl (cm->id);
2249   ch->client = idp;
2250   ch->identity = cm->identity;
2251   ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
2252   GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
2253                                       &ch->identity_pub);
2254   ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket2*)&cm[1]);
2255   rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
2256                                                    sizeof (uint64_t));
2257   GNUNET_asprintf (&lookup_query,
2258                    "%s.gnu",
2259                    rnd_label);
2260   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2261               "Looking for ABE key under %s\n", lookup_query);
2262
2263   ch->lookup_request
2264     = GNUNET_GNS_lookup (gns_handle,
2265                          lookup_query,
2266                          &ch->ticket.identity,
2267                          GNUNET_GNSRECORD_TYPE_ABE_KEY,
2268                          GNUNET_GNS_LO_LOCAL_MASTER,
2269                          &process_consume_abe_key,
2270                          ch);
2271   GNUNET_free (rnd_label);
2272   GNUNET_free (lookup_query);
2273   GNUNET_SERVICE_client_continue (idp->client);
2274 }
2275
2276 void
2277 attr_store_cont (void *cls,
2278                  int32_t success,
2279                  const char *emsg)
2280 {
2281   struct AttributeStoreHandle *as_handle = cls;
2282   struct GNUNET_MQ_Envelope *env;
2283   struct AttributeStoreResponseMessage *acr_msg;
2284
2285   if (GNUNET_SYSERR == success)
2286   {
2287     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2288                 "Failed to store attribute %s\n",
2289                 emsg);
2290     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
2291     return;
2292   }
2293
2294   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2295               "Sending ATTRIBUTE_STORE_RESPONSE message\n");
2296   env = GNUNET_MQ_msg (acr_msg,
2297                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
2298   acr_msg->id = htonl (as_handle->r_id);
2299   acr_msg->op_result = htonl (GNUNET_OK);
2300   GNUNET_MQ_send (as_handle->client->mq,
2301                   env);
2302   cleanup_as_handle (as_handle);
2303 }
2304
2305 static void
2306 attr_store_task (void *cls)
2307 {
2308   struct AttributeStoreHandle *as_handle = cls;
2309   struct GNUNET_GNSRECORD_Data rd[1];
2310   char* buf;
2311   size_t buf_size;
2312
2313   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2314               "Storing attribute\n");
2315   buf_size = attribute_serialize_get_size (as_handle->attribute);
2316   buf = GNUNET_malloc (buf_size);
2317
2318   attribute_serialize (as_handle->attribute,
2319                        buf);
2320
2321   /**
2322    * Encrypt the attribute value and store in namestore
2323    */
2324   rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
2325                                                  buf_size,
2326                                                  as_handle->attribute->name, //Policy
2327                                                  as_handle->abe_key,
2328                                                  (void**)&rd[0].data);
2329   GNUNET_free (buf);
2330   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
2331   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
2332   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
2333   as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
2334                                                      &as_handle->identity,
2335                                                      as_handle->attribute->name,
2336                                                      1,
2337                                                      rd,
2338                                                      &attr_store_cont,
2339                                                      as_handle);
2340   GNUNET_free ((void*)rd[0].data);
2341
2342 }
2343
2344
2345 static void
2346 store_after_abe_bootstrap (void *cls,
2347                            struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
2348 {
2349   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2350               "Finished ABE bootstrap\n");
2351   struct AttributeStoreHandle *ash = cls;
2352   ash->abe_key = abe_key;
2353   GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
2354 }
2355
2356 /**
2357  * Checks a store message
2358  *
2359  * @param cls client sending the message
2360  * @param sam message of type `struct AttributeStoreMessage`
2361  * @return #GNUNET_OK if @a im is well-formed
2362  */
2363 static int
2364 check_attribute_store_message(void *cls,
2365                               const struct AttributeStoreMessage *sam)
2366 {
2367   uint16_t size;
2368
2369   size = ntohs (sam->header.size);
2370   if (size <= sizeof (struct AttributeStoreMessage))
2371   {
2372     GNUNET_break (0);
2373     return GNUNET_SYSERR;
2374   }
2375   return GNUNET_OK;
2376 }
2377
2378
2379 /**
2380  *
2381  * Handler for store message
2382  *
2383  * @param cls unused
2384  * @param client who sent the message
2385  * @param message the message
2386  */
2387 static void
2388 handle_attribute_store_message (void *cls,
2389                                 const struct AttributeStoreMessage *sam)
2390 {
2391   struct AttributeStoreHandle *as_handle;
2392   struct IdpClient *idp = cls;
2393   size_t data_len;
2394   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2395               "Received ATTRIBUTE_STORE message\n");
2396
2397   data_len = ntohs (sam->attr_len);
2398
2399   as_handle = GNUNET_new (struct AttributeStoreHandle);
2400   as_handle->attribute = attribute_deserialize ((char*)&sam[1],
2401                                                 data_len);
2402
2403   as_handle->r_id = ntohl (sam->id);
2404   as_handle->identity = sam->identity;
2405   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
2406                                       &as_handle->identity_pkey);
2407
2408   GNUNET_SERVICE_client_continue (idp->client);
2409   as_handle->client = idp;
2410   bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle);
2411 }
2412
2413 static void
2414 cleanup_iter_handle (struct AttributeIterator *ai)
2415 {
2416   if (NULL != ai->abe_key)
2417     GNUNET_free (ai->abe_key);
2418   GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
2419                                ai->client->op_tail,
2420                                ai);
2421   GNUNET_free (ai);
2422 }
2423
2424 static void
2425 attr_iter_error (void *cls)
2426 {
2427   //struct AttributeIterator *ai = cls;
2428   //TODO
2429   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2430               "Failed to iterate over attributes\n");
2431   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
2432 }
2433
2434 static void
2435 attr_iter_finished (void *cls)
2436 {
2437   struct AttributeIterator *ai = cls;
2438   struct GNUNET_MQ_Envelope *env;
2439   struct AttributeResultMessage *arm;
2440
2441   env = GNUNET_MQ_msg (arm,
2442                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
2443   arm->id = htonl (ai->request_id);
2444   arm->attr_len = htons (0);
2445   GNUNET_MQ_send (ai->client->mq, env);
2446   cleanup_iter_handle (ai);
2447 }
2448
2449 static void
2450 attr_iter_cb (void *cls,
2451               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
2452               const char *label,
2453               unsigned int rd_count,
2454               const struct GNUNET_GNSRECORD_Data *rd)
2455 {
2456   struct AttributeIterator *ai = cls;
2457   struct AttributeResultMessage *arm;
2458   struct GNUNET_CRYPTO_AbeKey *key;
2459   struct GNUNET_MQ_Envelope *env;
2460   ssize_t msg_extra_len;
2461   char* attr_ser;
2462   char* attrs[2];
2463   char* data_tmp;
2464
2465   if (rd_count != 1)
2466   {
2467     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2468     return;
2469   }
2470
2471   if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
2472     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2473     return;
2474   }
2475   attrs[0] = (char*)label;
2476   attrs[1] = 0;
2477   key = GNUNET_CRYPTO_cpabe_create_key (ai->abe_key,
2478                                         attrs);
2479   msg_extra_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
2480                                                rd->data_size,
2481                                                key,
2482                                                (void**)&attr_ser);
2483   GNUNET_CRYPTO_cpabe_delete_key (key);
2484   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2485               "Found attribute: %s\n", label);
2486   env = GNUNET_MQ_msg_extra (arm,
2487                              msg_extra_len,
2488                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
2489   arm->id = htonl (ai->request_id);
2490   arm->attr_len = htons (msg_extra_len);
2491   GNUNET_CRYPTO_ecdsa_key_get_public (zone,
2492                                       &arm->identity);
2493   data_tmp = (char *) &arm[1];
2494   GNUNET_memcpy (data_tmp,
2495                  attr_ser,
2496                  msg_extra_len);
2497   GNUNET_MQ_send (ai->client->mq, env);
2498   GNUNET_free (attr_ser);
2499 }
2500
2501
2502 void
2503 iterate_after_abe_bootstrap (void *cls,
2504                              struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
2505 {
2506   struct AttributeIterator *ai = cls;
2507   ai->abe_key = abe_key;
2508   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
2509                                                      &ai->identity,
2510                                                      &attr_iter_error,
2511                                                      ai,
2512                                                      &attr_iter_cb,
2513                                                      ai,
2514                                                      &attr_iter_finished,
2515                                                      ai);
2516 }
2517
2518
2519 /**
2520  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_START message
2521  *
2522  * @param cls the client sending the message
2523  * @param zis_msg message from the client
2524  */
2525 static void
2526 handle_iteration_start (void *cls,
2527                         const struct AttributeIterationStartMessage *ais_msg)
2528 {
2529   struct IdpClient *idp = cls;
2530   struct AttributeIterator *ai;
2531
2532   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2533               "Received ATTRIBUTE_ITERATION_START message\n");
2534   ai = GNUNET_new (struct AttributeIterator);
2535   ai->request_id = ntohl (ais_msg->id);
2536   ai->client = idp;
2537   ai->identity = ais_msg->identity;
2538
2539   GNUNET_CONTAINER_DLL_insert (idp->op_head,
2540                                idp->op_tail,
2541                                ai);
2542   bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai);
2543   GNUNET_SERVICE_client_continue (idp->client);
2544 }
2545
2546
2547 /**
2548  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_STOP message
2549  *
2550  * @param cls the client sending the message
2551  * @param ais_msg message from the client
2552  */
2553 static void
2554 handle_iteration_stop (void *cls,
2555                        const struct AttributeIterationStopMessage *ais_msg)
2556 {
2557   struct IdpClient *idp = cls;
2558   struct AttributeIterator *ai;
2559   uint32_t rid;
2560
2561   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2562               "Received `%s' message\n",
2563               "ATTRIBUTE_ITERATION_STOP");
2564   rid = ntohl (ais_msg->id);
2565   for (ai = idp->op_head; NULL != ai; ai = ai->next)
2566     if (ai->request_id == rid)
2567       break;
2568   if (NULL == ai)
2569   {
2570     GNUNET_break (0);
2571     GNUNET_SERVICE_client_drop (idp->client);
2572     return;
2573   }
2574   GNUNET_CONTAINER_DLL_remove (idp->op_head,
2575                                idp->op_tail,
2576                                ai);
2577   GNUNET_free (ai);
2578   GNUNET_SERVICE_client_continue (idp->client);
2579 }
2580
2581
2582 /**
2583  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT message
2584  *
2585  * @param cls the client sending the message
2586  * @param message message from the client
2587  */
2588 static void
2589 handle_iteration_next (void *cls,
2590                        const struct AttributeIterationNextMessage *ais_msg)
2591 {
2592   struct IdpClient *idp = cls;
2593   struct AttributeIterator *ai;
2594   uint32_t rid;
2595
2596   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2597               "Received ATTRIBUTE_ITERATION_NEXT message\n");
2598   rid = ntohl (ais_msg->id);
2599   for (ai = idp->op_head; NULL != ai; ai = ai->next)
2600     if (ai->request_id == rid)
2601       break;
2602   if (NULL == ai)
2603   {
2604     GNUNET_break (0);
2605     GNUNET_SERVICE_client_drop (idp->client);
2606     return;
2607   }
2608   GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2609   GNUNET_SERVICE_client_continue (idp->client);
2610 }
2611
2612 /**
2613  * Ticket iteration processor result
2614  */
2615 enum ZoneIterationResult
2616 {
2617   /**
2618    * Iteration start.
2619    */
2620   IT_START = 0,
2621
2622   /**
2623    * Found tickets,
2624    * Continue to iterate with next iteration_next call
2625    */
2626   IT_SUCCESS_MORE_AVAILABLE = 1,
2627
2628   /**
2629    * Iteration complete
2630    */
2631   IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
2632 };
2633
2634
2635 /**
2636  * Context for ticket iteration
2637  */
2638 struct TicketIterationProcResult
2639 {
2640   /**
2641    * The ticket iteration handle
2642    */
2643   struct TicketIteration *ti;
2644
2645   /**
2646    * Iteration result: iteration done?
2647    * #IT_SUCCESS_MORE_AVAILABLE:  if there may be more results overall but
2648    * we got one for now and have sent it to the client
2649    * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
2650    * #IT_START: if we are still trying to find a result.
2651    */
2652   int res_iteration_finished;
2653
2654 };
2655
2656
2657
2658 /**
2659  * Process ticket from database
2660  *
2661  * @param cls struct TicketIterationProcResult
2662  * @param ticket the ticket
2663  * @param attrs the attributes
2664  */
2665 static void
2666 ticket_iterate_proc (void *cls,
2667                      const struct GNUNET_IDENTITY_PROVIDER_Ticket2 *ticket,
2668                      const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
2669 {
2670   struct TicketIterationProcResult *proc = cls;
2671
2672   if (NULL == ticket)
2673   {
2674     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2675                 "Iteration done\n");
2676     proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2677     return;
2678   }
2679   if ((NULL == ticket) || (NULL == attrs))
2680   {
2681     /* error */
2682     proc->res_iteration_finished = IT_START;
2683     GNUNET_break (0);
2684     return;
2685   }
2686   proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
2687   send_ticket_result (proc->ti->client,
2688                       proc->ti->r_id,
2689                       ticket,
2690                       attrs);
2691
2692 }
2693
2694 /**
2695  * Perform ticket iteration step
2696  *
2697  * @param ti ticket iterator to process
2698  */
2699 static void
2700 run_ticket_iteration_round (struct TicketIteration *ti)
2701 {
2702   struct TicketIterationProcResult proc;
2703   struct GNUNET_MQ_Envelope *env;
2704   struct TicketResultMessage *trm;
2705   int ret;
2706
2707   memset (&proc, 0, sizeof (proc));
2708   proc.ti = ti;
2709   proc.res_iteration_finished = IT_START;
2710   while (IT_START == proc.res_iteration_finished)
2711   {
2712     if (GNUNET_SYSERR ==
2713         (ret = TKT_database->iterate_tickets (TKT_database->cls,
2714                                               &ti->identity,
2715                                               ti->is_audience,
2716                                               ti->offset,
2717                                               &ticket_iterate_proc,
2718                                               &proc)))
2719     {
2720       GNUNET_break (0);
2721       break;
2722     }
2723     if (GNUNET_NO == ret)
2724       proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2725     ti->offset++;
2726   }
2727   if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
2728   {
2729     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2730                 "More results available\n");
2731     return; /* more later */
2732   }
2733   /* send empty response to indicate end of list */
2734   env = GNUNET_MQ_msg (trm,
2735                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
2736   trm->id = htonl (ti->r_id);
2737   GNUNET_MQ_send (ti->client->mq,
2738                   env);
2739   GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2740                                ti->client->ticket_iter_tail,
2741                                ti);
2742   GNUNET_free (ti);
2743 }
2744
2745 /**
2746  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START message
2747  *
2748  * @param cls the client sending the message
2749  * @param tis_msg message from the client
2750  */
2751 static void
2752 handle_ticket_iteration_start (void *cls,
2753                                const struct TicketIterationStartMessage *tis_msg)
2754 {
2755   struct IdpClient *client = cls;
2756   struct TicketIteration *ti;
2757
2758   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2759               "Received TICKET_ITERATION_START message\n");
2760   ti = GNUNET_new (struct TicketIteration);
2761   ti->r_id = ntohl (tis_msg->id);
2762   ti->offset = 0;
2763   ti->client = client;
2764   ti->identity = tis_msg->identity;
2765   ti->is_audience = ntohl (tis_msg->is_audience);
2766
2767   GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2768                                client->ticket_iter_tail,
2769                                ti);
2770   run_ticket_iteration_round (ti);
2771   GNUNET_SERVICE_client_continue (client->client);
2772 }
2773
2774
2775 /**
2776  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP message
2777  *
2778  * @param cls the client sending the message
2779  * @param tis_msg message from the client
2780  */
2781 static void
2782 handle_ticket_iteration_stop (void *cls,
2783                               const struct TicketIterationStopMessage *tis_msg)
2784 {
2785   struct IdpClient *client = cls;
2786   struct TicketIteration *ti;
2787   uint32_t rid;
2788
2789   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2790               "Received `%s' message\n",
2791               "TICKET_ITERATION_STOP");
2792   rid = ntohl (tis_msg->id);
2793   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2794     if (ti->r_id == rid)
2795       break;
2796   if (NULL == ti)
2797   {
2798     GNUNET_break (0);
2799     GNUNET_SERVICE_client_drop (client->client);
2800     return;
2801   }
2802   GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2803                                client->ticket_iter_tail,
2804                                ti);
2805   GNUNET_free (ti);
2806   GNUNET_SERVICE_client_continue (client->client);
2807 }
2808
2809
2810 /**
2811  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT message
2812  *
2813  * @param cls the client sending the message
2814  * @param message message from the client
2815  */
2816 static void
2817 handle_ticket_iteration_next (void *cls,
2818                               const struct TicketIterationNextMessage *tis_msg)
2819 {
2820   struct IdpClient *client = cls;
2821   struct TicketIteration *ti;
2822   uint32_t rid;
2823
2824   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2825               "Received TICKET_ITERATION_NEXT message\n");
2826   rid = ntohl (tis_msg->id);
2827   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2828     if (ti->r_id == rid)
2829       break;
2830   if (NULL == ti)
2831   {
2832     GNUNET_break (0);
2833     GNUNET_SERVICE_client_drop (client->client);
2834     return;
2835   }
2836   run_ticket_iteration_round (ti);
2837   GNUNET_SERVICE_client_continue (client->client);
2838 }
2839
2840
2841
2842
2843 /**
2844  * Main function that will be run
2845  *
2846  * @param cls closure
2847  * @param args remaining command-line arguments
2848  * @param cfgfile name of the configuration file used (for saving, can be NULL)
2849  * @param c configuration
2850  */
2851 static void
2852 run (void *cls,
2853      const struct GNUNET_CONFIGURATION_Handle *c,
2854      struct GNUNET_SERVICE_Handle *server)
2855 {
2856   char *database;
2857   cfg = c;
2858
2859   stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
2860
2861   //Connect to identity and namestore services
2862   ns_handle = GNUNET_NAMESTORE_connect (cfg);
2863   if (NULL == ns_handle)
2864   {
2865     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
2866   }
2867
2868   gns_handle = GNUNET_GNS_connect (cfg);
2869   if (NULL == gns_handle)
2870   {
2871     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
2872   }
2873   credential_handle = GNUNET_CREDENTIAL_connect (cfg);
2874   if (NULL == credential_handle)
2875   {
2876     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
2877   }
2878   identity_handle = GNUNET_IDENTITY_connect (cfg,
2879                                              NULL,
2880                                              NULL);
2881
2882   /* Loading DB plugin */
2883   if (GNUNET_OK !=
2884       GNUNET_CONFIGURATION_get_value_string (cfg,
2885                                              "identity-provider",
2886                                              "database",
2887                                              &database))
2888     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2889                 "No database backend configured\n");
2890   GNUNET_asprintf (&db_lib_name,
2891                    "libgnunet_plugin_identity_provider_%s",
2892                    database);
2893   TKT_database = GNUNET_PLUGIN_load (db_lib_name,
2894                                      (void *) cfg);
2895   GNUNET_free (database);
2896   if (NULL == TKT_database)
2897   {
2898     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2899                 "Could not load database backend `%s'\n",
2900                 db_lib_name);
2901     GNUNET_SCHEDULER_shutdown ();
2902     return;
2903   }
2904
2905   if (GNUNET_OK ==
2906       GNUNET_CONFIGURATION_get_value_time (cfg,
2907                                            "identity-provider",
2908                                            "TOKEN_EXPIRATION_INTERVAL",
2909                                            &token_expiration_interval))
2910   {
2911     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2912                 "Time window for zone iteration: %s\n",
2913                 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
2914                                                         GNUNET_YES));
2915   } else {
2916     token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
2917   }
2918
2919   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2920 }
2921
2922 /**
2923  * Called whenever a client is disconnected.
2924  *
2925  * @param cls closure
2926  * @param client identification of the client
2927  * @param app_ctx @a client
2928  */
2929 static void
2930 client_disconnect_cb (void *cls,
2931                       struct GNUNET_SERVICE_Client *client,
2932                       void *app_ctx)
2933 {
2934   struct IdpClient *idp = app_ctx;
2935   struct AttributeIterator *ai;
2936
2937   //TODO other operations
2938
2939   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2940               "Client %p disconnected\n",
2941               client);
2942
2943   while (NULL != (ai = idp->op_head))
2944   {
2945     GNUNET_CONTAINER_DLL_remove (idp->op_head,
2946                                  idp->op_tail,
2947                                  ai);
2948     GNUNET_free (ai);
2949   }
2950   GNUNET_free (idp);
2951 }
2952
2953
2954 /**
2955  * Add a client to our list of active clients.
2956  *
2957  * @param cls NULL
2958  * @param client client to add
2959  * @param mq message queue for @a client
2960  * @return internal namestore client structure for this client
2961  */
2962 static void *
2963 client_connect_cb (void *cls,
2964                    struct GNUNET_SERVICE_Client *client,
2965                    struct GNUNET_MQ_Handle *mq)
2966 {
2967   struct IdpClient *idp;
2968   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2969               "Client %p connected\n",
2970               client);
2971   idp = GNUNET_new (struct IdpClient);
2972   idp->client = client;
2973   idp->mq = mq;
2974   return idp;
2975 }
2976
2977
2978
2979 /**
2980  * Define "main" method using service macro.
2981  */
2982 GNUNET_SERVICE_MAIN
2983 ("identity-provider",
2984  GNUNET_SERVICE_OPTION_NONE,
2985  &run,
2986  &client_connect_cb,
2987  &client_disconnect_cb,
2988  NULL,
2989  GNUNET_MQ_hd_var_size (issue_message,
2990                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE,
2991                         struct IssueMessage,
2992                         NULL),
2993  GNUNET_MQ_hd_var_size (exchange_message,
2994                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE,
2995                         struct ExchangeMessage,
2996                         NULL),
2997  GNUNET_MQ_hd_var_size (attribute_store_message,
2998                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
2999                         struct AttributeStoreMessage,
3000                         NULL),
3001  GNUNET_MQ_hd_fixed_size (iteration_start, 
3002                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
3003                           struct AttributeIterationStartMessage,
3004                           NULL),
3005  GNUNET_MQ_hd_fixed_size (iteration_next, 
3006                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
3007                           struct AttributeIterationNextMessage,
3008                           NULL),
3009  GNUNET_MQ_hd_fixed_size (iteration_stop, 
3010                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
3011                           struct AttributeIterationStopMessage,
3012                           NULL),
3013  GNUNET_MQ_hd_var_size (ticket_issue_message,
3014                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE,
3015                         struct TicketIssueMessage,
3016                         NULL),
3017  GNUNET_MQ_hd_var_size (consume_ticket_message,
3018                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
3019                         struct ConsumeTicketMessage,
3020                         NULL),
3021  GNUNET_MQ_hd_fixed_size (ticket_iteration_start, 
3022                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
3023                           struct TicketIterationStartMessage,
3024                           NULL),
3025  GNUNET_MQ_hd_fixed_size (ticket_iteration_next, 
3026                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
3027                           struct TicketIterationNextMessage,
3028                           NULL),
3029  GNUNET_MQ_hd_fixed_size (ticket_iteration_stop, 
3030                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
3031                           struct TicketIterationStopMessage,
3032                           NULL),
3033
3034  GNUNET_MQ_handler_end());
3035  /* end of gnunet-service-identity-provider.c */