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