-fixes
[oweals/gnunet.git] / src / identity-provider / gnunet-service-identity-provider.c
1 /*
2    This file is part of GNUnet.
3    Copyright (C) 2012-2015 GNUnet e.V.
4
5    GNUnet is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published
7    by the Free Software Foundation; either version 3, or (at your
8    option) any later version.
9
10    GNUnet is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with GNUnet; see the file COPYING.  If not, write to the
17    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18    Boston, MA 02110-1301, USA.
19    */
20 /**
21  * @author Martin Schanzenbach
22  * @file src/identity-provider/gnunet-service-identity-provider.c
23  * @brief Identity Token Service
24  *
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_identity_service.h"
31 #include "gnunet_gnsrecord_lib.h"
32 #include "gnunet_namestore_service.h"
33 #include "gnunet_credential_service.h"
34 #include "gnunet_statistics_service.h"
35 #include "gnunet_gns_service.h"
36 #include "gnunet_identity_provider_plugin.h"
37 #include "gnunet_signatures.h"
38 #include "identity_provider.h"
39 #include "identity_attribute.h"
40
41 /**
42  * First pass state
43  */
44 #define STATE_INIT 0
45
46 /**
47  * Normal operation state
48  */
49 #define STATE_POST_INIT 1
50
51 /**
52  * Minimum interval between updates
53  */
54 #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
55
56 /**
57  * Standard token expiration time
58  */
59 #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
60
61 /**
62  * Identity handle
63  */
64 static struct GNUNET_IDENTITY_Handle *identity_handle;
65
66 /**
67  * Database handle
68  */
69 static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database;
70
71 /**
72  * Name of DB plugin
73  */
74 static char *db_lib_name;
75
76 /**
77  * Token expiration interval
78  */
79 static struct GNUNET_TIME_Relative token_expiration_interval;
80
81 /**
82  * Namestore handle
83  */
84 static struct GNUNET_NAMESTORE_Handle *ns_handle;
85
86 /**
87  * GNS handle
88  */
89 static struct GNUNET_GNS_Handle *gns_handle;
90
91 /**
92  * Credential handle
93  */
94 static struct GNUNET_CREDENTIAL_Handle *credential_handle;
95
96 /**
97  * Namestore qe
98  */
99 static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
100
101 /**
102  * Namestore iterator
103  */
104 static struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
105
106 /**
107  * Timeout task
108  */
109 static struct GNUNET_SCHEDULER_Task *timeout_task;
110
111 /**
112  * Update task
113  */
114 static struct GNUNET_SCHEDULER_Task *update_task;
115
116
117 /**
118  * Currently processed token
119  */
120 static struct IdentityToken *token;
121
122 /**
123  * Label for currently processed token
124  */
125 static char* label;
126
127 /**
128  * Scopes for processed token
129  */
130 static char* scopes;
131
132 /**
133  * Handle to the statistics service.
134  */
135 static struct GNUNET_STATISTICS_Handle *stats;
136
137 /**
138  * Our configuration.
139  */
140 static const struct GNUNET_CONFIGURATION_Handle *cfg;
141
142 /**
143  * An idp client
144  */
145 struct IdpClient;
146
147 /**
148  * A ticket iteration operation.
149  */
150 struct TicketIteration
151 {
152   /**
153    * DLL
154    */
155   struct TicketIteration *next;
156
157   /**
158    * DLL
159    */
160   struct TicketIteration *prev;
161
162   /**
163    * Client which intiated this zone iteration
164    */
165   struct IdpClient *client;
166
167   /**
168    * Key of the identity we are iterating over.
169    */
170   struct GNUNET_CRYPTO_EcdsaPublicKey identity;
171
172   /**
173    * Identity is audience
174    */
175   uint32_t is_audience;
176
177   /**
178    * The operation id fot the iteration in the response for the client
179    */
180   uint32_t r_id;
181
182   /**
183    * Offset of the iteration used to address next result of the 
184    * iteration in the store
185    *
186    * Initialy set to 0 in handle_iteration_start
187    * Incremented with by every call to handle_iteration_next
188    */
189   uint32_t offset;
190
191 };
192
193
194
195 /**
196  * Callback after an ABE bootstrap
197  *
198  * @param cls closure
199  * @param abe_key the ABE key that exists or was created
200  */
201 typedef void
202 (*AbeBootstrapResult) (void *cls,
203                        struct GNUNET_CRYPTO_AbeMasterKey *abe_key);
204
205
206 struct AbeBootstrapHandle
207 {
208   /**
209    * Function to call when finished
210    */
211   AbeBootstrapResult proc;
212
213   /**
214    * Callback closure
215    */
216   char *proc_cls;
217
218   /**
219    * Key of the zone we are iterating over.
220    */
221   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
222
223   /**
224    * Namestore Queue Entry
225    */
226   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
227
228   /**
229    * The issuer egos ABE master key
230    */
231   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
232 };
233
234 /**
235  * An attribute iteration operation.
236  */
237 struct AttributeIterator
238 {
239   /**
240    * Next element in the DLL
241    */
242   struct AttributeIterator *next;
243
244   /**
245    * Previous element in the DLL
246    */
247   struct AttributeIterator *prev;
248
249   /**
250    * IDP client which intiated this zone iteration
251    */
252   struct IdpClient *client;
253
254   /**
255    * Key of the zone we are iterating over.
256    */
257   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
258
259   /**
260    * The issuer egos ABE master key
261    */
262   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
263
264   /**
265    * Namestore iterator
266    */
267   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
268
269   /**
270    * The operation id fot the zone iteration in the response for the client
271    */
272   uint32_t request_id;
273
274 };
275
276
277
278 /**
279  * An idp client
280  */
281 struct IdpClient
282 {
283
284   /**
285    * The client
286    */
287   struct GNUNET_SERVICE_Client *client;
288
289   /**
290    * Message queue for transmission to @e client
291    */
292   struct GNUNET_MQ_Handle *mq;
293   
294   /**
295    * Head of the DLL of
296    * Attribute iteration operations in 
297    * progress initiated by this client
298    */
299   struct AttributeIterator *op_head;
300
301   /**
302    * Tail of the DLL of
303    * Attribute iteration operations 
304    * in progress initiated by this client
305    */
306   struct AttributeIterator *op_tail;
307
308   /**
309    * Head of DLL of ticket iteration ops
310    */
311   struct TicketIteration *ticket_iter_head;
312
313   /**
314    * Tail of DLL of ticket iteration ops
315    */
316   struct TicketIteration *ticket_iter_tail;
317
318
319   /**
320    * Head of DLL of ticket revocation ops
321    */
322   struct TicketRevocationHandle *revocation_list_head;
323
324   /**
325    * Tail of DLL of ticket revocation ops
326    */
327   struct TicketRevocationHandle *revocation_list_tail;
328 };
329
330
331
332 struct AttributeStoreHandle
333 {
334
335   /**
336    * Client connection
337    */
338   struct IdpClient *client;
339
340   /**
341    * Identity
342    */
343   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
344
345   /**
346    * Identity pubkey
347    */
348   struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
349
350   /**
351    * The issuer egos ABE master key
352    */
353   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
354
355   /**
356    * QueueEntry
357    */
358   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
359
360   /**
361    * The attribute to store
362    */
363   struct GNUNET_IDENTITY_PROVIDER_Attribute *attribute;
364
365   /**
366    * request id
367    */
368   uint32_t r_id;
369 };
370
371
372 /* Prototype */
373 struct ParallelLookup;
374
375 struct ConsumeTicketHandle
376 {
377
378   /**
379    * Client connection
380    */
381   struct IdpClient *client;
382
383   /**
384    * Ticket
385    */
386   struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
387
388   /**
389    * LookupRequest
390    */
391   struct GNUNET_GNS_LookupRequest *lookup_request;
392
393   /**
394    * Audience Key
395    */
396   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
397
398   /**
399    * Audience Key
400    */
401   struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
402
403   /**
404    * Lookup DLL
405    */
406   struct ParallelLookup *parallel_lookups_head;
407
408   /**
409    * Lookup DLL
410    */
411   struct ParallelLookup *parallel_lookups_tail;
412   
413   /**
414    * Kill task
415    */
416   struct GNUNET_SCHEDULER_Task *kill_task;
417
418   /**
419    * The ABE key
420    */
421   struct GNUNET_CRYPTO_AbeKey *key;
422
423   /**
424    * Attributes
425    */
426   struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
427
428   /**
429    * request id
430    */
431   uint32_t r_id;
432 };
433
434 /**
435  * Handle for a parallel GNS lookup job
436  */
437 struct ParallelLookup
438 {
439   /* DLL */
440   struct ParallelLookup *next;
441
442   /* DLL */
443   struct ParallelLookup *prev;
444
445   /* The GNS request */
446   struct GNUNET_GNS_LookupRequest *lookup_request;
447
448   /* The handle the return to */
449   struct ConsumeTicketHandle *handle;
450
451   /* The label to look up */
452   char *label;
453 };
454
455 /**
456  * Ticket revocation request handle
457  */
458 struct TicketRevocationHandle
459 {
460   /**
461    * DLL
462    */
463   struct TicketRevocationHandle *next;
464
465   /**
466    * DLL
467    */
468   struct TicketRevocationHandle *prev;
469
470   /**
471    * Client connection
472    */
473   struct IdpClient *client;
474
475   /**
476    * Attributes to issue
477    */
478   struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
479
480   /**
481    * Issuer Key
482    */
483   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
484
485   /**
486    * Ticket to issue
487    */
488   struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
489
490   /**
491    * QueueEntry
492    */
493   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
494
495   /**
496    * Namestore iterator
497    */
498   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
499
500   /**
501    * The ABE master key
502    */
503   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
504
505   /**
506    * Offset
507    */
508   uint32_t offset;
509
510   /**
511    * request id
512    */
513   uint32_t r_id;
514 };
515
516
517
518 /**
519  * Ticket issue request handle
520  */
521 struct TicketIssueHandle
522 {
523
524   /**
525    * Client connection
526    */
527   struct IdpClient *client;
528
529   /**
530    * Attributes to issue
531    */
532   struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
533
534   /**
535    * Issuer Key
536    */
537   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
538
539   /**
540    * Ticket to issue
541    */
542   struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
543
544   /**
545    * QueueEntry
546    */
547   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
548
549   /**
550    * request id
551    */
552   uint32_t r_id;
553 };
554
555
556 /**
557  * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
558  *
559  */
560 struct EgoEntry
561 {
562   /**
563    * DLL
564    */
565   struct EgoEntry *next;
566
567   /**
568    * DLL
569    */
570   struct EgoEntry *prev;
571
572   /**
573    * Ego handle
574    */
575   struct GNUNET_IDENTITY_Ego *ego;
576
577   /**
578    * Attribute map. Contains the attributes as json_t
579    */
580   struct GNUNET_CONTAINER_MultiHashMap *attr_map;
581
582 };
583
584 /**
585  * Cleanup task
586  */
587 static void
588 cleanup()
589 {
590   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
591               "Cleaning up\n");
592   if (NULL != stats)
593   {
594     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
595     stats = NULL;
596   }
597   GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
598                                               TKT_database)); 
599   GNUNET_free (db_lib_name);
600   db_lib_name = NULL;
601   if (NULL != timeout_task)
602     GNUNET_SCHEDULER_cancel (timeout_task);
603   if (NULL != update_task)
604     GNUNET_SCHEDULER_cancel (update_task);
605   if (NULL != identity_handle)
606     GNUNET_IDENTITY_disconnect (identity_handle);
607   if (NULL != gns_handle)
608     GNUNET_GNS_disconnect (gns_handle);
609   if (NULL != credential_handle)
610     GNUNET_CREDENTIAL_disconnect (credential_handle);
611   if (NULL != ns_it)
612     GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
613   if (NULL != ns_qe)
614     GNUNET_NAMESTORE_cancel (ns_qe);
615   if (NULL != ns_handle)
616     GNUNET_NAMESTORE_disconnect (ns_handle);
617   if (NULL != token)
618     GNUNET_free (token);
619   if (NULL != label)
620     GNUNET_free (label);
621
622 }
623
624 /**
625  * Shutdown task
626  *
627  * @param cls NULL
628  * @param tc task context
629  */
630 static void
631 do_shutdown (void *cls)
632 {
633   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
634               "Shutting down...\n");
635   cleanup();
636 }
637
638 /**
639  * Finished storing newly bootstrapped ABE key
640  */
641 static void
642 bootstrap_store_cont (void *cls,
643                       int32_t success,
644                       const char *emsg)
645 {
646   struct AbeBootstrapHandle *abh = cls;
647   if (GNUNET_SYSERR == success)
648   {
649     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
650                 "Failed to bootstrap ABE master %s\n",
651                 emsg);
652     abh->proc (abh->proc_cls, NULL);
653     GNUNET_free (abh->abe_key);
654     GNUNET_free (abh);
655     return;
656   }
657   abh->proc (abh->proc_cls, abh->abe_key);
658   GNUNET_free (abh);
659 }
660
661 /**
662  * Generates and stores a new ABE key
663  */
664 static void
665 bootstrap_store_task (void *cls)
666 {
667   struct AbeBootstrapHandle *abh = cls;
668   struct GNUNET_GNSRECORD_Data rd[1];
669
670   rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (abh->abe_key,
671                                                               (void**)&rd[0].data);
672   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
673   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
674   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
675   abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
676                                                &abh->identity,
677                                                "+",
678                                                1,
679                                                rd,
680                                                &bootstrap_store_cont,
681                                                abh);
682 }
683
684 /**
685  * Error checking for ABE master
686  */
687 static void
688 bootstrap_abe_error (void *cls)
689 {
690   struct AbeBootstrapHandle *abh = cls;
691   GNUNET_free (abh);
692   abh->proc (abh->proc_cls, NULL);
693   GNUNET_free (abh);
694 }
695
696
697 /**
698  * Handle ABE lookup in namestore
699  */
700 static void
701 bootstrap_abe_result (void *cls,
702                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
703                       const char *label,
704                       unsigned int rd_count,
705                       const struct GNUNET_GNSRECORD_Data *rd)
706 {
707   struct AbeBootstrapHandle *abh = cls;
708   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
709   int i;
710
711   for (i=0;i<rd_count;i++) {
712     if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
713       continue;
714     abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key ((void**)rd[i].data,
715                                                           rd[i].data_size);
716     abh->proc (abh->proc_cls, abe_key);
717     GNUNET_free (abh);
718     return;
719   }
720
721   //No ABE master found, bootstrapping...
722   abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
723   GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
724 }
725
726 /**
727  * Bootstrap ABE master if it does not yet exists.
728  * Will call the AbeBootstrapResult processor when done.
729  * will always recreate the ABE key of GNUNET_YES == recreate
730  */
731 static void
732 bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
733                AbeBootstrapResult proc,
734                void* cls,
735                int recreate)
736 {
737   struct AbeBootstrapHandle *abh;
738
739   abh = GNUNET_new (struct AbeBootstrapHandle);
740   abh->proc = proc;
741   abh->proc_cls = cls;
742   abh->identity = *identity;
743   if (GNUNET_YES == recreate)
744   {
745     abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
746     GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
747   } else {
748     abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
749                                                   identity,
750                                                   "+",
751                                                   &bootstrap_abe_error,
752                                                   abh,
753                                                   &bootstrap_abe_result,
754                                                   abh);
755   }
756 }
757
758
759
760 static int
761 create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
762                          struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
763                          struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
764 {
765   struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
766
767   GNUNET_CRYPTO_hash_to_enc (new_key_hash,
768                              &new_key_hash_str);
769   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
770   static const char ctx_key[] = "gnuid-aes-ctx-key";
771   GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
772                      new_key_hash, sizeof (struct GNUNET_HashCode),
773                      ctx_key, strlen (ctx_key),
774                      NULL, 0);
775   static const char ctx_iv[] = "gnuid-aes-ctx-iv";
776   GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
777                      new_key_hash, sizeof (struct GNUNET_HashCode),
778                      ctx_iv, strlen (ctx_iv),
779                      NULL, 0);
780   return GNUNET_OK;
781 }
782
783 static void
784 cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
785 {
786   if (NULL != handle->attrs)
787     attribute_list_destroy (handle->attrs);
788   if (NULL != handle->ns_qe)
789     GNUNET_NAMESTORE_cancel (handle->ns_qe);
790   GNUNET_free (handle);
791 }
792
793
794 static void
795 send_ticket_result (struct IdpClient *client,
796                     uint32_t r_id,
797                     const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
798                     const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
799 {
800   struct TicketResultMessage *irm;
801   struct GNUNET_MQ_Envelope *env;
802   struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
803
804   /* store ticket in DB */
805   if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
806                                                ticket,
807                                                attrs))
808   {
809     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
810                 "Unable to store ticket after issue\n");
811     GNUNET_break (0);
812   }
813
814   env = GNUNET_MQ_msg_extra (irm,
815                              sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
816                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
817   ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
818   *ticket_buf = *ticket;
819   irm->id = htonl (r_id);
820   GNUNET_MQ_send (client->mq,
821                   env);
822 }
823
824 static void
825 store_ticket_issue_cont (void *cls,
826                          int32_t success,
827                          const char *emsg)
828 {
829   struct TicketIssueHandle *handle = cls;
830
831   handle->ns_qe = NULL;
832   if (GNUNET_SYSERR == success)
833   {
834     cleanup_ticket_issue_handle (handle);
835     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
836                 "Unknown Error\n");
837     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
838     return;
839   }
840   send_ticket_result (handle->client,
841                       handle->r_id,
842                       &handle->ticket,
843                       handle->attrs);
844   cleanup_ticket_issue_handle (handle);
845 }
846
847
848
849 int
850 serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
851                         const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs,
852                         const struct GNUNET_CRYPTO_AbeKey *rp_key,
853                         struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
854                         char **result)
855 {
856   struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
857   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
858   char *enc_keyinfo;
859   char *serialized_key;
860   char *buf;
861   char *write_ptr;
862   char attrs_str_len;
863   ssize_t size;
864
865   struct GNUNET_CRYPTO_SymmetricSessionKey skey;
866   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
867   struct GNUNET_HashCode new_key_hash;
868   ssize_t enc_size;
869
870   size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key,
871                                             (void**)&serialized_key);
872   attrs_str_len = 0;
873   for (le = attrs->list_head; NULL != le; le = le->next) {
874     attrs_str_len += strlen (le->attribute->name) + 1;
875   }
876   buf = GNUNET_malloc (attrs_str_len + size);
877   write_ptr = buf;
878   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
879               "Writing attributes\n");
880   for (le = attrs->list_head; NULL != le; le = le->next) {
881     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
882                 "%s\n", le->attribute->name);
883
884
885     GNUNET_memcpy (write_ptr,
886                    le->attribute->name,
887                    strlen (le->attribute->name));
888     write_ptr[strlen (le->attribute->name)] = ',';
889     write_ptr += strlen (le->attribute->name) + 1;
890   }
891   write_ptr--;
892   write_ptr[0] = '\0'; //replace last , with a 0-terminator
893   write_ptr++;
894   GNUNET_memcpy (write_ptr,
895                  serialized_key,
896                  size);
897   // ECDH keypair E = eG
898   *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
899   GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
900                                       &ecdh_pubkey);
901   enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
902   // Derived key K = H(eB)
903   GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
904                                                         &ticket->audience,
905                                                         &new_key_hash));
906   create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
907   enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
908                                               size + attrs_str_len,
909                                               &skey, &iv,
910                                               enc_keyinfo);
911   *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
912                            enc_size);
913   GNUNET_memcpy (*result,
914                  &ecdh_pubkey,
915                  sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
916   GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
917                  enc_keyinfo,
918                  enc_size);
919   GNUNET_free (enc_keyinfo);
920   return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
921 }
922
923
924
925 static void
926 issue_ticket_after_abe_bootstrap (void *cls,
927                                   struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
928 {
929   struct TicketIssueHandle *ih = cls;
930   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
931   struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
932   struct GNUNET_GNSRECORD_Data code_record[1];
933   struct GNUNET_CRYPTO_AbeKey *rp_key;
934   char *code_record_data;
935   char **attrs;
936   char *label;
937   int attrs_len;
938   int i;
939   size_t code_record_len;
940
941   //Create new ABE key for RP
942   attrs_len = 0;
943   for (le = ih->attrs->list_head; NULL != le; le = le->next)
944     attrs_len++;
945   attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
946   i = 0;
947   for (le = ih->attrs->list_head; NULL != le; le = le->next) {
948     attrs[i] = (char*) le->attribute->name;
949     i++;
950   }
951   attrs[i] = NULL;
952   rp_key = GNUNET_CRYPTO_cpabe_create_key (abe_key,
953                                            attrs);
954
955   //TODO review this wireformat
956   code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
957                                             ih->attrs,
958                                             rp_key,
959                                             &ecdhe_privkey,
960                                             &code_record_data);
961   code_record[0].data = code_record_data;
962   code_record[0].data_size = code_record_len;
963   code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
964   code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
965   code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
966
967   label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
968                                                sizeof (uint64_t));
969   //Publish record
970   ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
971                                               &ih->identity,
972                                               label,
973                                               1,
974                                               code_record,
975                                               &store_ticket_issue_cont,
976                                               ih);
977   GNUNET_free (ecdhe_privkey);
978   GNUNET_free (label);
979   GNUNET_free (attrs);
980   GNUNET_free (code_record_data);
981 }
982
983
984 /**
985  * Checks a ticket issue message
986  *
987  * @param cls client sending the message
988  * @param im message of type `struct TicketIssueMessage`
989  * @return #GNUNET_OK if @a im is well-formed
990  */
991 static int
992 check_issue_ticket_message(void *cls,
993                            const struct IssueTicketMessage *im)
994 {
995   uint16_t size;
996
997   size = ntohs (im->header.size);
998   if (size <= sizeof (struct IssueTicketMessage))
999   {
1000     GNUNET_break (0);
1001     return GNUNET_SYSERR;
1002   }
1003   return GNUNET_OK;
1004 }
1005
1006
1007 /**
1008  *
1009  * Handler for ticket issue message
1010  *
1011  * @param cls unused
1012  * @param client who sent the message
1013  * @param message the message
1014  */
1015 static void
1016 handle_issue_ticket_message (void *cls,
1017                              const struct IssueTicketMessage *im)
1018 {
1019   struct TicketIssueHandle *ih;
1020   struct IdpClient *idp = cls;
1021   size_t attrs_len;
1022
1023   ih = GNUNET_new (struct TicketIssueHandle);
1024   attrs_len = ntohs (im->attr_len);
1025   ih->attrs = attribute_list_deserialize ((char*)&im[1], attrs_len);
1026   ih->r_id = ntohl (im->id);
1027   ih->client = idp;
1028   ih->identity = im->identity;
1029   GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
1030                                       &ih->ticket.identity);
1031   ih->ticket.audience = im->rp;
1032   ih->ticket.rnd =
1033     GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1034                               UINT64_MAX);
1035   bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
1036   GNUNET_SERVICE_client_continue (idp->client);
1037
1038 }
1039
1040 /**********************************************************
1041  * Revocation
1042  **********************************************************/
1043
1044 /**
1045  * Cleanup revoke handle
1046  */
1047 static void
1048 cleanup_revoke_ticket_handle (struct TicketRevocationHandle *handle)
1049 {
1050   if (NULL != handle->attrs)
1051     attribute_list_destroy (handle->attrs);
1052   if (NULL != handle->abe_key)
1053     GNUNET_free (handle->abe_key);
1054   if (NULL != handle->ns_qe)
1055     GNUNET_NAMESTORE_cancel (handle->ns_qe);
1056   if (NULL != handle->ns_it)
1057     GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
1058   GNUNET_free (handle);
1059 }
1060
1061
1062 /**
1063  * Send revocation result
1064  */
1065 static void
1066 send_revocation_finished (struct TicketRevocationHandle *rh,
1067                           uint32_t success)
1068 {
1069   struct GNUNET_MQ_Envelope *env;
1070   struct RevokeTicketResultMessage *trm;
1071
1072   env = GNUNET_MQ_msg (trm,
1073                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT);
1074   trm->id = htonl (rh->r_id);
1075   trm->success = htonl (success);
1076   GNUNET_MQ_send (rh->client->mq,
1077                   env);
1078   GNUNET_CONTAINER_DLL_remove (rh->client->revocation_list_head,
1079                                rh->client->revocation_list_tail,
1080                                rh);
1081   cleanup_revoke_ticket_handle (rh);
1082 }
1083
1084
1085 /**
1086  * Process ticket from database
1087  *
1088  * @param cls struct TicketIterationProcResult
1089  * @param ticket the ticket
1090  * @param attrs the attributes
1091  */
1092 static void
1093 ticket_reissue_proc (void *cls,
1094                      const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1095                      const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs);
1096
1097
1098 static void
1099 reissue_ticket_cont (void *cls,
1100                      int32_t success,
1101                      const char *emsg)
1102 {
1103   struct TicketRevocationHandle *rh = cls;
1104
1105   rh->ns_qe = NULL;
1106   if (GNUNET_SYSERR == success)
1107   {
1108     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1109                 "Unknown Error\n");
1110     send_revocation_finished (rh, GNUNET_SYSERR);
1111     cleanup_revoke_ticket_handle (rh);
1112     return;
1113   }
1114   rh->offset++;
1115   GNUNET_assert (GNUNET_SYSERR !=
1116                  TKT_database->iterate_tickets (TKT_database->cls,
1117                                                 &rh->ticket.identity,
1118                                                 GNUNET_NO,
1119                                                 rh->offset,
1120                                                 &ticket_reissue_proc,
1121                                                 rh));
1122 }
1123
1124
1125
1126 /**
1127  * Process ticket from database
1128  *
1129  * @param cls struct TicketIterationProcResult
1130  * @param ticket the ticket
1131  * @param attrs the attributes
1132  */
1133 static void
1134 ticket_reissue_proc (void *cls,
1135                      const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1136                      const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
1137 {
1138   struct TicketRevocationHandle *rh = cls;
1139   const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs_to_reissue;
1140   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1141   struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
1142   struct GNUNET_GNSRECORD_Data code_record[1];
1143   struct GNUNET_CRYPTO_AbeKey *rp_key;
1144   char *code_record_data;
1145   char **attr_arr;
1146   char *label;
1147   int attrs_len;
1148   int i;
1149   size_t code_record_len;
1150
1151
1152   if (NULL == ticket)
1153   {
1154     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1155                 "Iteration done\n");
1156     send_revocation_finished (rh, GNUNET_OK);
1157     cleanup_revoke_ticket_handle (rh);
1158     return;
1159   }
1160   //Create new ABE key for RP
1161   attrs_len = 0;
1162   attrs_to_reissue = attrs;
1163
1164   /* If this is the RP we want to revoke attributes of, the do so */
1165   if (0 == memcmp (&ticket->audience,
1166                    &rh->ticket.audience,
1167                    sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
1168     attrs_to_reissue = rh->attrs;
1169
1170   for (le = attrs_to_reissue->list_head; NULL != le; le = le->next)
1171     attrs_len++;
1172   attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1173   i = 0;
1174   for (le = attrs_to_reissue->list_head; NULL != le; le = le->next) {
1175     attr_arr[i] = (char*) le->attribute->name;
1176     i++;
1177   }
1178   attr_arr[i] = NULL;
1179   rp_key = GNUNET_CRYPTO_cpabe_create_key (rh->abe_key,
1180                                            attr_arr);
1181
1182   //TODO review this wireformat
1183   code_record_len = serialize_abe_keyinfo2 (&rh->ticket,
1184                                             rh->attrs,
1185                                             rp_key,
1186                                             &ecdhe_privkey,
1187                                             &code_record_data);
1188   code_record[0].data = code_record_data;
1189   code_record[0].data_size = code_record_len;
1190   code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1191   code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1192   code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1193
1194   label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
1195                                                sizeof (uint64_t));
1196   //Publish record
1197   rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1198                                               &rh->identity,
1199                                               label,
1200                                               1,
1201                                               code_record,
1202                                               &reissue_ticket_cont,
1203                                               rh);
1204   GNUNET_free (ecdhe_privkey);
1205   GNUNET_free (label);
1206   GNUNET_free (attr_arr);
1207   GNUNET_free (code_record_data);
1208
1209 }
1210
1211
1212
1213
1214 /* Prototype for below function */
1215 static void
1216 attr_reenc_cont (void *cls,
1217                  int32_t success,
1218                  const char *emsg);
1219
1220 /**
1221  * Revoke next attribte by reencryption with
1222  * new ABE master
1223  */
1224 static void
1225 reenc_next_attribute (struct TicketRevocationHandle *rh)
1226 {
1227   struct GNUNET_GNSRECORD_Data rd[1];
1228   char* buf;
1229   size_t buf_size;
1230
1231   buf_size = attribute_serialize_get_size (rh->attrs->list_head->attribute);
1232   buf = GNUNET_malloc (buf_size);
1233
1234   attribute_serialize (rh->attrs->list_head->attribute,
1235                        buf);
1236
1237   /**
1238    * Encrypt the attribute value and store in namestore
1239    */
1240   rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1241                                                  buf_size,
1242                                                  rh->attrs->list_head->attribute->name, //Policy
1243                                                  rh->abe_key,
1244                                                  (void**)&rd[0].data);
1245   GNUNET_free (buf);
1246   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1247   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1248   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1249   rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1250                                               &rh->identity,
1251                                               rh->attrs->list_head->attribute->name,
1252                                               1,
1253                                               rd,
1254                                               &attr_reenc_cont,
1255                                               rh);
1256   GNUNET_free ((void*)rd[0].data);
1257
1258 }
1259
1260 /**
1261  * Namestore callback after revoked attribute
1262  * is stored
1263  */
1264 static void
1265 attr_reenc_cont (void *cls,
1266                  int32_t success,
1267                  const char *emsg)
1268 {
1269   struct TicketRevocationHandle *rh = cls;
1270   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1271   int ret;
1272
1273   if (GNUNET_SYSERR == success)
1274   {
1275     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1276                 "Failed to reencrypt attribute %s\n",
1277                 emsg);
1278     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1279     return;
1280   }
1281   le = rh->attrs->list_head;
1282   GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1283                                rh->attrs->list_tail,
1284                                rh->attrs->list_head);
1285   GNUNET_free (le->attribute);
1286   GNUNET_free (le);
1287
1288   if (NULL == rh->attrs->list_head)
1289   {
1290     /* Done, issue new keys */
1291     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1292                 "Revocation Phase IV: Reissuing Tickets\n");
1293     if (GNUNET_SYSERR ==
1294         (ret = TKT_database->iterate_tickets (TKT_database->cls,
1295                                               &rh->ticket.identity,
1296                                               GNUNET_NO,
1297                                               rh->offset,
1298                                               &ticket_reissue_proc,
1299                                               rh)))
1300     {
1301       GNUNET_break (0);
1302     }
1303     return;
1304   }
1305   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1306               "Re-encrypting next attribute\n");
1307   reenc_next_attribute (rh);
1308 }
1309
1310
1311 /**
1312  * Start reencryption with newly generated ABE master
1313  */
1314 static void
1315 reenc_after_abe_bootstrap (void *cls,
1316                            struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1317 {
1318   struct TicketRevocationHandle *rh = cls;
1319   GNUNET_free (rh->abe_key);
1320   GNUNET_assert (NULL != abe_key);
1321   rh->abe_key = abe_key;
1322
1323   if (NULL == rh->attrs->list_head)
1324   {
1325     /* No attributes to reencrypt */
1326     send_revocation_finished (rh, GNUNET_OK);
1327     cleanup_revoke_ticket_handle (rh);
1328     return;
1329   } else {
1330     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1331                 "Revocation Phase III: Re-encrypting attributes\n");
1332     reenc_next_attribute (rh);
1333   }
1334 }
1335
1336
1337 /**
1338  * Collecting attributes failed... abort.
1339  */
1340 static void
1341 revoke_collect_iter_error (void *cls)
1342 {
1343   struct TicketRevocationHandle *rh = cls;
1344
1345   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1346               "Failed to iterate over attributes\n");
1347   rh->ns_it = NULL;
1348   send_revocation_finished (rh, GNUNET_SYSERR);
1349   cleanup_revoke_ticket_handle (rh);
1350 }
1351
1352 /**
1353  * Done decrypting existing attributes.
1354  */
1355 static void
1356 revoke_collect_iter_finished (void *cls)
1357 {
1358   struct TicketRevocationHandle *rh = cls;
1359   rh->ns_it = NULL;
1360   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1361               "Revocation Phase II: Invalidating old ABE Master\n");
1362   /* Bootstrap new abe key */
1363   bootstrap_abe (&rh->identity, &reenc_after_abe_bootstrap, rh, GNUNET_YES);
1364 }
1365
1366 /**
1367  * Decrypt existing attribute and store it
1368  * We will revoke it by reencrypting it with a new ABE master key.
1369  */
1370 static void
1371 revoke_collect_iter_cb (void *cls,
1372                         const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1373                         const char *label,
1374                         unsigned int rd_count,
1375                         const struct GNUNET_GNSRECORD_Data *rd)
1376 {
1377   struct TicketRevocationHandle *rh = cls;
1378   struct GNUNET_CRYPTO_AbeKey *key;
1379   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
1380   ssize_t attr_len;
1381   char* attr_ser;
1382   char* attrs[2];
1383
1384   if (rd_count != 1)
1385   {
1386     GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it);
1387     return;
1388   }
1389
1390   if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
1391     GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it);
1392     return;
1393   }
1394   attrs[0] = (char*)label;
1395   attrs[1] = 0;
1396   key = GNUNET_CRYPTO_cpabe_create_key (rh->abe_key,
1397                                         attrs);
1398   attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
1399                                           rd->data_size,
1400                                           key,
1401                                           (void**)&attr_ser);
1402   GNUNET_CRYPTO_cpabe_delete_key (key);
1403   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1404               "Attribute to reencrypt: %s\n", label);
1405   le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
1406   le->attribute = attribute_deserialize (attr_ser, attr_len);
1407   GNUNET_CONTAINER_DLL_insert_tail (rh->attrs->list_head,
1408                                     rh->attrs->list_tail,
1409                                     le);
1410   GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it);
1411 }
1412
1413 /**
1414  * Start attribute collection for revocation
1415  */
1416 static void
1417 collect_after_abe_bootstrap (void *cls,
1418                              struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1419 {
1420   struct TicketRevocationHandle *rh = cls;
1421
1422   rh->abe_key = cls;
1423   GNUNET_assert (NULL != abe_key);
1424   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1425               "Revocation Phase I: Collecting attributes\n");
1426   /* Reencrypt all attributes with new key */
1427   rh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1428                                                      &rh->identity,
1429                                                      &revoke_collect_iter_error,
1430                                                      rh,
1431                                                      &revoke_collect_iter_cb,
1432                                                      rh,
1433                                                      &revoke_collect_iter_finished,
1434                                                      rh);
1435
1436 }
1437
1438
1439 /**
1440  * Checks a ticket revocation message
1441  *
1442  * @param cls client sending the message
1443  * @param im message of type `struct RevokeTicketMessage`
1444  * @return #GNUNET_OK if @a im is well-formed
1445  */
1446 static int
1447 check_revoke_ticket_message(void *cls,
1448                             const struct RevokeTicketMessage *im)
1449 {
1450   uint16_t size;
1451
1452   size = ntohs (im->header.size);
1453   if (size <= sizeof (struct RevokeTicketMessage))
1454   {
1455     GNUNET_break (0);
1456     return GNUNET_SYSERR;
1457   }
1458   return GNUNET_OK;
1459 }
1460
1461
1462 /**
1463  *
1464  * Handler for ticket revocation message
1465  *
1466  * @param cls unused
1467  * @param client who sent the message
1468  * @param message the message
1469  */
1470 static void
1471 handle_revoke_ticket_message (void *cls,
1472                               const struct RevokeTicketMessage *rm)
1473 {
1474   struct TicketRevocationHandle *rh;
1475   struct IdpClient *idp = cls;
1476   struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
1477   size_t attrs_len;
1478
1479   rh = GNUNET_new (struct TicketRevocationHandle);
1480   attrs_len = ntohs (rm->attrs_len);
1481   ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1];
1482   if (0 < attrs_len)
1483     rh->attrs = attribute_list_deserialize ((char*)&ticket[1], attrs_len);
1484   rh->ticket = *ticket;
1485   rh->r_id = ntohl (rm->id);
1486   rh->client = idp;
1487   rh->identity = rm->identity;
1488   GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
1489                                       &rh->ticket.identity);
1490   GNUNET_CONTAINER_DLL_insert (idp->revocation_list_head,
1491                                idp->revocation_list_tail,
1492                                rh);
1493   bootstrap_abe (&rh->identity, &collect_after_abe_bootstrap, rh, GNUNET_NO);
1494   GNUNET_SERVICE_client_continue (idp->client);
1495
1496 }
1497
1498
1499 static void
1500 cleanup_as_handle (struct AttributeStoreHandle *handle)
1501 {
1502   if (NULL != handle->attribute)
1503     GNUNET_free (handle->attribute);
1504   if (NULL != handle->abe_key)
1505     GNUNET_free (handle->abe_key);
1506   GNUNET_free (handle);
1507 }
1508
1509 /**
1510  * Checks a ticket consume message
1511  *
1512  * @param cls client sending the message
1513  * @param im message of type `struct ConsumeTicketMessage`
1514  * @return #GNUNET_OK if @a im is well-formed
1515  */
1516 static int
1517 check_consume_ticket_message(void *cls,
1518                              const struct ConsumeTicketMessage *cm)
1519 {
1520   uint16_t size;
1521
1522   size = ntohs (cm->header.size);
1523   if (size <= sizeof (struct ConsumeTicketMessage))
1524   {
1525     GNUNET_break (0);
1526     return GNUNET_SYSERR;
1527   }
1528   return GNUNET_OK;
1529 }
1530
1531 static void
1532 process_parallel_lookup2 (void *cls, uint32_t rd_count,
1533                           const struct GNUNET_GNSRECORD_Data *rd)
1534 {
1535   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1536               "Parallel lookup finished (count=%u)\n", rd_count);
1537   struct ParallelLookup *parallel_lookup = cls;
1538   struct ConsumeTicketHandle *handle = parallel_lookup->handle;
1539   struct ConsumeTicketResultMessage *crm;
1540   struct GNUNET_MQ_Envelope *env;
1541   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *attr_le;
1542   char *data;
1543   char *data_tmp;
1544   size_t attr_len;
1545   size_t attrs_len;
1546
1547   GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1548                                handle->parallel_lookups_tail,
1549                                parallel_lookup);
1550   GNUNET_free (parallel_lookup->label);
1551   GNUNET_free (parallel_lookup);
1552   if (1 != rd_count)
1553     GNUNET_break(0);//TODO
1554   if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1555   {
1556     attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
1557                                             rd->data_size,
1558                                             handle->key,
1559                                             (void**)&data);
1560     attr_le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
1561     attr_le->attribute = attribute_deserialize (data,
1562                                                 attr_len);
1563     GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
1564                                  handle->attrs->list_tail,
1565                                  attr_le);
1566     GNUNET_free (data);
1567   }
1568   if (NULL != handle->parallel_lookups_head)
1569     return; //Wait for more
1570   /* Else we are done */
1571
1572   /* Store ticket in DB */
1573   if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1574                                                &handle->ticket,
1575                                                handle->attrs))
1576   {
1577     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1578                 "Unable to store ticket after consume\n");
1579     GNUNET_break (0);
1580   }
1581
1582   GNUNET_SCHEDULER_cancel (handle->kill_task);
1583   attrs_len = attribute_list_serialize_get_size (handle->attrs);
1584   env = GNUNET_MQ_msg_extra (crm,
1585                              attrs_len,
1586                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
1587   crm->id = htonl (handle->r_id);
1588   crm->attrs_len = htons (attrs_len);
1589   crm->identity = handle->ticket.identity;
1590   data_tmp = (char *) &crm[1];
1591   attribute_list_serialize (handle->attrs,
1592                             data_tmp);
1593   GNUNET_MQ_send (handle->client->mq, env);
1594 }
1595
1596 void
1597 abort_parallel_lookups2 (void *cls)
1598 {
1599   struct ConsumeTicketHandle *handle = cls;
1600   struct ParallelLookup *lu;
1601   struct ParallelLookup *tmp;
1602   struct AttributeResultMessage *arm;
1603   struct GNUNET_MQ_Envelope *env;
1604
1605   for (lu = handle->parallel_lookups_head;
1606        NULL != lu;) {
1607     GNUNET_GNS_lookup_cancel (lu->lookup_request);
1608     GNUNET_free (lu->label);
1609     tmp = lu->next;
1610     GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1611                                  handle->parallel_lookups_tail,
1612                                  lu);
1613     GNUNET_free (lu);
1614     lu = tmp;
1615   }
1616   env = GNUNET_MQ_msg (arm,
1617                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1618   arm->id = htonl (handle->r_id);
1619   arm->attr_len = htons (0);
1620   GNUNET_MQ_send (handle->client->mq, env);
1621
1622 }
1623
1624 static void
1625 cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
1626 {
1627   if (NULL != handle->key)
1628     GNUNET_free (handle->key);
1629   GNUNET_free (handle);
1630 }
1631
1632
1633 static void
1634 process_consume_abe_key (void *cls, uint32_t rd_count,
1635                          const struct GNUNET_GNSRECORD_Data *rd)
1636 {
1637   struct ConsumeTicketHandle *handle = cls;
1638   struct GNUNET_HashCode new_key_hash;
1639   struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1640   struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1641   struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1642   struct ParallelLookup *parallel_lookup;
1643   size_t size;
1644   char *buf;
1645   char *scope;
1646   char *lookup_query;
1647
1648   handle->lookup_request = NULL;
1649   if (1 != rd_count)
1650   {
1651     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1652                 "Number of keys %d != 1.",
1653                 rd_count);
1654     cleanup_consume_ticket_handle (handle);
1655     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1656     return;
1657   }
1658
1659   //Decrypt
1660   ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1661
1662   buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1663
1664   //Calculate symmetric key from ecdh parameters
1665   GNUNET_assert (GNUNET_OK == 
1666                  GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
1667                                            ecdh_key,
1668                                            &new_key_hash));
1669   create_sym_key_from_ecdh (&new_key_hash,
1670                             &enc_key,
1671                             &enc_iv);
1672   size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1673                                           rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1674                                           &enc_key,
1675                                           &enc_iv,
1676                                           buf);
1677
1678   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1679               "Decrypted bytes: %zd Expected bytes: %zd\n",
1680               size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1681
1682   scopes = GNUNET_strdup (buf);
1683   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1684               "Scopes %s\n", scopes);
1685   handle->key = GNUNET_CRYPTO_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1686                                                      rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1687                                                      - strlen (scopes) - 1);
1688
1689   for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1690   {
1691     GNUNET_asprintf (&lookup_query,
1692                      "%s.gnu",
1693                      scope);
1694     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1695                 "Looking up %s\n", lookup_query);
1696     parallel_lookup = GNUNET_new (struct ParallelLookup);
1697     parallel_lookup->handle = handle;
1698     parallel_lookup->label = GNUNET_strdup (scope);
1699     parallel_lookup->lookup_request
1700       = GNUNET_GNS_lookup (gns_handle,
1701                            lookup_query,
1702                            &handle->ticket.identity,
1703                            GNUNET_GNSRECORD_TYPE_ID_ATTR,
1704                            GNUNET_GNS_LO_LOCAL_MASTER,
1705                            &process_parallel_lookup2,
1706                            parallel_lookup);
1707     GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1708                                  handle->parallel_lookups_tail,
1709                                  parallel_lookup);
1710     GNUNET_free (lookup_query);
1711   }
1712   handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1713                                                     &abort_parallel_lookups2,
1714                                                     handle);
1715 }
1716
1717
1718 /**
1719  *
1720  * Handler for ticket issue message
1721  *
1722  * @param cls unused
1723  * @param client who sent the message
1724  * @param message the message
1725  */
1726 static void
1727 handle_consume_ticket_message (void *cls,
1728                                const struct ConsumeTicketMessage *cm)
1729 {
1730   struct ConsumeTicketHandle *ch;
1731   struct IdpClient *idp = cls;
1732   char* lookup_query;
1733   char* rnd_label;
1734
1735   ch = GNUNET_new (struct ConsumeTicketHandle);
1736   ch->r_id = ntohl (cm->id);
1737   ch->client = idp;
1738   ch->identity = cm->identity;
1739   ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
1740   GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
1741                                       &ch->identity_pub);
1742   ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
1743   rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
1744                                                    sizeof (uint64_t));
1745   GNUNET_asprintf (&lookup_query,
1746                    "%s.gnu",
1747                    rnd_label);
1748   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1749               "Looking for ABE key under %s\n", lookup_query);
1750
1751   ch->lookup_request
1752     = GNUNET_GNS_lookup (gns_handle,
1753                          lookup_query,
1754                          &ch->ticket.identity,
1755                          GNUNET_GNSRECORD_TYPE_ABE_KEY,
1756                          GNUNET_GNS_LO_LOCAL_MASTER,
1757                          &process_consume_abe_key,
1758                          ch);
1759   GNUNET_free (rnd_label);
1760   GNUNET_free (lookup_query);
1761   GNUNET_SERVICE_client_continue (idp->client);
1762 }
1763
1764 static void
1765 attr_store_cont (void *cls,
1766                  int32_t success,
1767                  const char *emsg)
1768 {
1769   struct AttributeStoreHandle *as_handle = cls;
1770   struct GNUNET_MQ_Envelope *env;
1771   struct AttributeStoreResponseMessage *acr_msg;
1772
1773   if (GNUNET_SYSERR == success)
1774   {
1775     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1776                 "Failed to store attribute %s\n",
1777                 emsg);
1778     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1779     return;
1780   }
1781
1782   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1783               "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1784   env = GNUNET_MQ_msg (acr_msg,
1785                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
1786   acr_msg->id = htonl (as_handle->r_id);
1787   acr_msg->op_result = htonl (GNUNET_OK);
1788   GNUNET_MQ_send (as_handle->client->mq,
1789                   env);
1790   cleanup_as_handle (as_handle);
1791 }
1792
1793 static void
1794 attr_store_task (void *cls)
1795 {
1796   struct AttributeStoreHandle *as_handle = cls;
1797   struct GNUNET_GNSRECORD_Data rd[1];
1798   char* buf;
1799   size_t buf_size;
1800
1801   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1802               "Storing attribute\n");
1803   buf_size = attribute_serialize_get_size (as_handle->attribute);
1804   buf = GNUNET_malloc (buf_size);
1805
1806   attribute_serialize (as_handle->attribute,
1807                        buf);
1808
1809   /**
1810    * Encrypt the attribute value and store in namestore
1811    */
1812   rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1813                                                  buf_size,
1814                                                  as_handle->attribute->name, //Policy
1815                                                  as_handle->abe_key,
1816                                                  (void**)&rd[0].data);
1817   GNUNET_free (buf);
1818   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1819   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1820   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1821   as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1822                                                      &as_handle->identity,
1823                                                      as_handle->attribute->name,
1824                                                      1,
1825                                                      rd,
1826                                                      &attr_store_cont,
1827                                                      as_handle);
1828   GNUNET_free ((void*)rd[0].data);
1829
1830 }
1831
1832
1833 static void
1834 store_after_abe_bootstrap (void *cls,
1835                            struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1836 {
1837   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1838               "Finished ABE bootstrap\n");
1839   struct AttributeStoreHandle *ash = cls;
1840   ash->abe_key = abe_key;
1841   GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1842 }
1843
1844 /**
1845  * Checks a store message
1846  *
1847  * @param cls client sending the message
1848  * @param sam message of type `struct AttributeStoreMessage`
1849  * @return #GNUNET_OK if @a im is well-formed
1850  */
1851 static int
1852 check_attribute_store_message(void *cls,
1853                               const struct AttributeStoreMessage *sam)
1854 {
1855   uint16_t size;
1856
1857   size = ntohs (sam->header.size);
1858   if (size <= sizeof (struct AttributeStoreMessage))
1859   {
1860     GNUNET_break (0);
1861     return GNUNET_SYSERR;
1862   }
1863   return GNUNET_OK;
1864 }
1865
1866
1867 /**
1868  *
1869  * Handler for store message
1870  *
1871  * @param cls unused
1872  * @param client who sent the message
1873  * @param message the message
1874  */
1875 static void
1876 handle_attribute_store_message (void *cls,
1877                                 const struct AttributeStoreMessage *sam)
1878 {
1879   struct AttributeStoreHandle *as_handle;
1880   struct IdpClient *idp = cls;
1881   size_t data_len;
1882   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1883               "Received ATTRIBUTE_STORE message\n");
1884
1885   data_len = ntohs (sam->attr_len);
1886
1887   as_handle = GNUNET_new (struct AttributeStoreHandle);
1888   as_handle->attribute = attribute_deserialize ((char*)&sam[1],
1889                                                 data_len);
1890
1891   as_handle->r_id = ntohl (sam->id);
1892   as_handle->identity = sam->identity;
1893   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1894                                       &as_handle->identity_pkey);
1895
1896   GNUNET_SERVICE_client_continue (idp->client);
1897   as_handle->client = idp;
1898   bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
1899 }
1900
1901 static void
1902 cleanup_iter_handle (struct AttributeIterator *ai)
1903 {
1904   if (NULL != ai->abe_key)
1905     GNUNET_free (ai->abe_key);
1906   GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
1907                                ai->client->op_tail,
1908                                ai);
1909   GNUNET_free (ai);
1910 }
1911
1912 static void
1913 attr_iter_error (void *cls)
1914 {
1915   //struct AttributeIterator *ai = cls;
1916   //TODO
1917   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1918               "Failed to iterate over attributes\n");
1919   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1920 }
1921
1922 static void
1923 attr_iter_finished (void *cls)
1924 {
1925   struct AttributeIterator *ai = cls;
1926   struct GNUNET_MQ_Envelope *env;
1927   struct AttributeResultMessage *arm;
1928
1929   env = GNUNET_MQ_msg (arm,
1930                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1931   arm->id = htonl (ai->request_id);
1932   arm->attr_len = htons (0);
1933   GNUNET_MQ_send (ai->client->mq, env);
1934   cleanup_iter_handle (ai);
1935 }
1936
1937 static void
1938 attr_iter_cb (void *cls,
1939               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1940               const char *label,
1941               unsigned int rd_count,
1942               const struct GNUNET_GNSRECORD_Data *rd)
1943 {
1944   struct AttributeIterator *ai = cls;
1945   struct AttributeResultMessage *arm;
1946   struct GNUNET_CRYPTO_AbeKey *key;
1947   struct GNUNET_MQ_Envelope *env;
1948   ssize_t msg_extra_len;
1949   char* attr_ser;
1950   char* attrs[2];
1951   char* data_tmp;
1952
1953   if (rd_count != 1)
1954   {
1955     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1956     return;
1957   }
1958
1959   if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
1960     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1961     return;
1962   }
1963   attrs[0] = (char*)label;
1964   attrs[1] = 0;
1965   key = GNUNET_CRYPTO_cpabe_create_key (ai->abe_key,
1966                                         attrs);
1967   msg_extra_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
1968                                                rd->data_size,
1969                                                key,
1970                                                (void**)&attr_ser);
1971   GNUNET_CRYPTO_cpabe_delete_key (key);
1972   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1973               "Found attribute: %s\n", label);
1974   env = GNUNET_MQ_msg_extra (arm,
1975                              msg_extra_len,
1976                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1977   arm->id = htonl (ai->request_id);
1978   arm->attr_len = htons (msg_extra_len);
1979   GNUNET_CRYPTO_ecdsa_key_get_public (zone,
1980                                       &arm->identity);
1981   data_tmp = (char *) &arm[1];
1982   GNUNET_memcpy (data_tmp,
1983                  attr_ser,
1984                  msg_extra_len);
1985   GNUNET_MQ_send (ai->client->mq, env);
1986   GNUNET_free (attr_ser);
1987 }
1988
1989
1990 void
1991 iterate_after_abe_bootstrap (void *cls,
1992                              struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1993 {
1994   struct AttributeIterator *ai = cls;
1995   ai->abe_key = abe_key;
1996   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1997                                                      &ai->identity,
1998                                                      &attr_iter_error,
1999                                                      ai,
2000                                                      &attr_iter_cb,
2001                                                      ai,
2002                                                      &attr_iter_finished,
2003                                                      ai);
2004 }
2005
2006
2007 /**
2008  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_START message
2009  *
2010  * @param cls the client sending the message
2011  * @param zis_msg message from the client
2012  */
2013 static void
2014 handle_iteration_start (void *cls,
2015                         const struct AttributeIterationStartMessage *ais_msg)
2016 {
2017   struct IdpClient *idp = cls;
2018   struct AttributeIterator *ai;
2019
2020   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2021               "Received ATTRIBUTE_ITERATION_START message\n");
2022   ai = GNUNET_new (struct AttributeIterator);
2023   ai->request_id = ntohl (ais_msg->id);
2024   ai->client = idp;
2025   ai->identity = ais_msg->identity;
2026
2027   GNUNET_CONTAINER_DLL_insert (idp->op_head,
2028                                idp->op_tail,
2029                                ai);
2030   bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
2031   GNUNET_SERVICE_client_continue (idp->client);
2032 }
2033
2034
2035 /**
2036  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_STOP message
2037  *
2038  * @param cls the client sending the message
2039  * @param ais_msg message from the client
2040  */
2041 static void
2042 handle_iteration_stop (void *cls,
2043                        const struct AttributeIterationStopMessage *ais_msg)
2044 {
2045   struct IdpClient *idp = cls;
2046   struct AttributeIterator *ai;
2047   uint32_t rid;
2048
2049   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2050               "Received `%s' message\n",
2051               "ATTRIBUTE_ITERATION_STOP");
2052   rid = ntohl (ais_msg->id);
2053   for (ai = idp->op_head; NULL != ai; ai = ai->next)
2054     if (ai->request_id == rid)
2055       break;
2056   if (NULL == ai)
2057   {
2058     GNUNET_break (0);
2059     GNUNET_SERVICE_client_drop (idp->client);
2060     return;
2061   }
2062   GNUNET_CONTAINER_DLL_remove (idp->op_head,
2063                                idp->op_tail,
2064                                ai);
2065   GNUNET_free (ai);
2066   GNUNET_SERVICE_client_continue (idp->client);
2067 }
2068
2069
2070 /**
2071  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT message
2072  *
2073  * @param cls the client sending the message
2074  * @param message message from the client
2075  */
2076 static void
2077 handle_iteration_next (void *cls,
2078                        const struct AttributeIterationNextMessage *ais_msg)
2079 {
2080   struct IdpClient *idp = cls;
2081   struct AttributeIterator *ai;
2082   uint32_t rid;
2083
2084   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2085               "Received ATTRIBUTE_ITERATION_NEXT message\n");
2086   rid = ntohl (ais_msg->id);
2087   for (ai = idp->op_head; NULL != ai; ai = ai->next)
2088     if (ai->request_id == rid)
2089       break;
2090   if (NULL == ai)
2091   {
2092     GNUNET_break (0);
2093     GNUNET_SERVICE_client_drop (idp->client);
2094     return;
2095   }
2096   GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2097   GNUNET_SERVICE_client_continue (idp->client);
2098 }
2099
2100 /**
2101  * Ticket iteration processor result
2102  */
2103 enum ZoneIterationResult
2104 {
2105   /**
2106    * Iteration start.
2107    */
2108   IT_START = 0,
2109
2110   /**
2111    * Found tickets,
2112    * Continue to iterate with next iteration_next call
2113    */
2114   IT_SUCCESS_MORE_AVAILABLE = 1,
2115
2116   /**
2117    * Iteration complete
2118    */
2119   IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
2120 };
2121
2122
2123 /**
2124  * Context for ticket iteration
2125  */
2126 struct TicketIterationProcResult
2127 {
2128   /**
2129    * The ticket iteration handle
2130    */
2131   struct TicketIteration *ti;
2132
2133   /**
2134    * Iteration result: iteration done?
2135    * #IT_SUCCESS_MORE_AVAILABLE:  if there may be more results overall but
2136    * we got one for now and have sent it to the client
2137    * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
2138    * #IT_START: if we are still trying to find a result.
2139    */
2140   int res_iteration_finished;
2141
2142 };
2143
2144 static void
2145 cleanup_ticket_iter_handle (struct TicketIteration *ti)
2146 {
2147   GNUNET_free (ti);
2148 }
2149
2150 /**
2151  * Process ticket from database
2152  *
2153  * @param cls struct TicketIterationProcResult
2154  * @param ticket the ticket
2155  * @param attrs the attributes
2156  */
2157 static void
2158 ticket_iterate_proc (void *cls,
2159                      const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
2160                      const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
2161 {
2162   struct TicketIterationProcResult *proc = cls;
2163
2164   if (NULL == ticket)
2165   {
2166     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2167                 "Iteration done\n");
2168     proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2169     return;
2170   }
2171   proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
2172   send_ticket_result (proc->ti->client,
2173                       proc->ti->r_id,
2174                       ticket,
2175                       attrs);
2176
2177 }
2178
2179 /**
2180  * Perform ticket iteration step
2181  *
2182  * @param ti ticket iterator to process
2183  */
2184 static void
2185 run_ticket_iteration_round (struct TicketIteration *ti)
2186 {
2187   struct TicketIterationProcResult proc;
2188   struct GNUNET_MQ_Envelope *env;
2189   struct TicketResultMessage *trm;
2190   int ret;
2191
2192   memset (&proc, 0, sizeof (proc));
2193   proc.ti = ti;
2194   proc.res_iteration_finished = IT_START;
2195   while (IT_START == proc.res_iteration_finished)
2196   {
2197     if (GNUNET_SYSERR ==
2198         (ret = TKT_database->iterate_tickets (TKT_database->cls,
2199                                               &ti->identity,
2200                                               ti->is_audience,
2201                                               ti->offset,
2202                                               &ticket_iterate_proc,
2203                                               &proc)))
2204     {
2205       GNUNET_break (0);
2206       break;
2207     }
2208     if (GNUNET_NO == ret)
2209       proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2210     ti->offset++;
2211   }
2212   if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
2213   {
2214     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2215                 "More results available\n");
2216     return; /* more later */
2217   }
2218   /* send empty response to indicate end of list */
2219   env = GNUNET_MQ_msg (trm,
2220                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
2221   trm->id = htonl (ti->r_id);
2222   GNUNET_MQ_send (ti->client->mq,
2223                   env);
2224   GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2225                                ti->client->ticket_iter_tail,
2226                                ti);
2227   cleanup_ticket_iter_handle (ti);
2228 }
2229
2230 /**
2231  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START message
2232  *
2233  * @param cls the client sending the message
2234  * @param tis_msg message from the client
2235  */
2236 static void
2237 handle_ticket_iteration_start (void *cls,
2238                                const struct TicketIterationStartMessage *tis_msg)
2239 {
2240   struct IdpClient *client = cls;
2241   struct TicketIteration *ti;
2242
2243   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2244               "Received TICKET_ITERATION_START message\n");
2245   ti = GNUNET_new (struct TicketIteration);
2246   ti->r_id = ntohl (tis_msg->id);
2247   ti->offset = 0;
2248   ti->client = client;
2249   ti->identity = tis_msg->identity;
2250   ti->is_audience = ntohl (tis_msg->is_audience);
2251
2252   GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2253                                client->ticket_iter_tail,
2254                                ti);
2255   run_ticket_iteration_round (ti);
2256   GNUNET_SERVICE_client_continue (client->client);
2257 }
2258
2259
2260 /**
2261  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP message
2262  *
2263  * @param cls the client sending the message
2264  * @param tis_msg message from the client
2265  */
2266 static void
2267 handle_ticket_iteration_stop (void *cls,
2268                               const struct TicketIterationStopMessage *tis_msg)
2269 {
2270   struct IdpClient *client = cls;
2271   struct TicketIteration *ti;
2272   uint32_t rid;
2273
2274   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2275               "Received `%s' message\n",
2276               "TICKET_ITERATION_STOP");
2277   rid = ntohl (tis_msg->id);
2278   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2279     if (ti->r_id == rid)
2280       break;
2281   if (NULL == ti)
2282   {
2283     GNUNET_break (0);
2284     GNUNET_SERVICE_client_drop (client->client);
2285     return;
2286   }
2287   GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2288                                client->ticket_iter_tail,
2289                                ti);
2290   cleanup_ticket_iter_handle (ti);
2291   GNUNET_SERVICE_client_continue (client->client);
2292 }
2293
2294
2295 /**
2296  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT message
2297  *
2298  * @param cls the client sending the message
2299  * @param message message from the client
2300  */
2301 static void
2302 handle_ticket_iteration_next (void *cls,
2303                               const struct TicketIterationNextMessage *tis_msg)
2304 {
2305   struct IdpClient *client = cls;
2306   struct TicketIteration *ti;
2307   uint32_t rid;
2308
2309   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2310               "Received TICKET_ITERATION_NEXT message\n");
2311   rid = ntohl (tis_msg->id);
2312   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2313     if (ti->r_id == rid)
2314       break;
2315   if (NULL == ti)
2316   {
2317     GNUNET_break (0);
2318     GNUNET_SERVICE_client_drop (client->client);
2319     return;
2320   }
2321   run_ticket_iteration_round (ti);
2322   GNUNET_SERVICE_client_continue (client->client);
2323 }
2324
2325
2326
2327
2328 /**
2329  * Main function that will be run
2330  *
2331  * @param cls closure
2332  * @param args remaining command-line arguments
2333  * @param cfgfile name of the configuration file used (for saving, can be NULL)
2334  * @param c configuration
2335  */
2336 static void
2337 run (void *cls,
2338      const struct GNUNET_CONFIGURATION_Handle *c,
2339      struct GNUNET_SERVICE_Handle *server)
2340 {
2341   char *database;
2342   cfg = c;
2343
2344   stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
2345
2346   //Connect to identity and namestore services
2347   ns_handle = GNUNET_NAMESTORE_connect (cfg);
2348   if (NULL == ns_handle)
2349   {
2350     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
2351   }
2352
2353   gns_handle = GNUNET_GNS_connect (cfg);
2354   if (NULL == gns_handle)
2355   {
2356     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
2357   }
2358   credential_handle = GNUNET_CREDENTIAL_connect (cfg);
2359   if (NULL == credential_handle)
2360   {
2361     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
2362   }
2363   identity_handle = GNUNET_IDENTITY_connect (cfg,
2364                                              NULL,
2365                                              NULL);
2366
2367   /* Loading DB plugin */
2368   if (GNUNET_OK !=
2369       GNUNET_CONFIGURATION_get_value_string (cfg,
2370                                              "identity-provider",
2371                                              "database",
2372                                              &database))
2373     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2374                 "No database backend configured\n");
2375   GNUNET_asprintf (&db_lib_name,
2376                    "libgnunet_plugin_identity_provider_%s",
2377                    database);
2378   TKT_database = GNUNET_PLUGIN_load (db_lib_name,
2379                                      (void *) cfg);
2380   GNUNET_free (database);
2381   if (NULL == TKT_database)
2382   {
2383     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2384                 "Could not load database backend `%s'\n",
2385                 db_lib_name);
2386     GNUNET_SCHEDULER_shutdown ();
2387     return;
2388   }
2389
2390   if (GNUNET_OK ==
2391       GNUNET_CONFIGURATION_get_value_time (cfg,
2392                                            "identity-provider",
2393                                            "TOKEN_EXPIRATION_INTERVAL",
2394                                            &token_expiration_interval))
2395   {
2396     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2397                 "Time window for zone iteration: %s\n",
2398                 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
2399                                                         GNUNET_YES));
2400   } else {
2401     token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
2402   }
2403
2404   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2405 }
2406
2407 /**
2408  * Called whenever a client is disconnected.
2409  *
2410  * @param cls closure
2411  * @param client identification of the client
2412  * @param app_ctx @a client
2413  */
2414 static void
2415 client_disconnect_cb (void *cls,
2416                       struct GNUNET_SERVICE_Client *client,
2417                       void *app_ctx)
2418 {
2419   struct IdpClient *idp = app_ctx;
2420   struct AttributeIterator *ai;
2421   struct TicketIteration *ti;
2422   struct TicketRevocationHandle *rh;
2423
2424   //TODO other operations
2425
2426   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2427               "Client %p disconnected\n",
2428               client);
2429
2430   while (NULL != (ai = idp->op_head))
2431   {
2432     GNUNET_CONTAINER_DLL_remove (idp->op_head,
2433                                  idp->op_tail,
2434                                  ai);
2435     GNUNET_free (ai);
2436   }
2437   while (NULL != (rh = idp->revocation_list_head))
2438   {
2439     GNUNET_CONTAINER_DLL_remove (idp->revocation_list_head,
2440                                  idp->revocation_list_tail,
2441                                  rh);
2442     cleanup_revoke_ticket_handle (rh);
2443   }
2444   while (NULL != (ti = idp->ticket_iter_head))
2445   {
2446     GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
2447                                  idp->ticket_iter_tail,
2448                                  ti);
2449     cleanup_ticket_iter_handle (ti);
2450   }
2451   GNUNET_free (idp);
2452 }
2453
2454
2455 /**
2456  * Add a client to our list of active clients.
2457  *
2458  * @param cls NULL
2459  * @param client client to add
2460  * @param mq message queue for @a client
2461  * @return internal namestore client structure for this client
2462  */
2463 static void *
2464 client_connect_cb (void *cls,
2465                    struct GNUNET_SERVICE_Client *client,
2466                    struct GNUNET_MQ_Handle *mq)
2467 {
2468   struct IdpClient *idp;
2469   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2470               "Client %p connected\n",
2471               client);
2472   idp = GNUNET_new (struct IdpClient);
2473   idp->client = client;
2474   idp->mq = mq;
2475   return idp;
2476 }
2477
2478
2479
2480 /**
2481  * Define "main" method using service macro.
2482  */
2483 GNUNET_SERVICE_MAIN
2484 ("identity-provider",
2485  GNUNET_SERVICE_OPTION_NONE,
2486  &run,
2487  &client_connect_cb,
2488  &client_disconnect_cb,
2489  NULL,
2490  GNUNET_MQ_hd_var_size (attribute_store_message,
2491                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
2492                         struct AttributeStoreMessage,
2493                         NULL),
2494  GNUNET_MQ_hd_fixed_size (iteration_start, 
2495                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
2496                           struct AttributeIterationStartMessage,
2497                           NULL),
2498  GNUNET_MQ_hd_fixed_size (iteration_next, 
2499                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
2500                           struct AttributeIterationNextMessage,
2501                           NULL),
2502  GNUNET_MQ_hd_fixed_size (iteration_stop, 
2503                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
2504                           struct AttributeIterationStopMessage,
2505                           NULL),
2506  GNUNET_MQ_hd_var_size (issue_ticket_message,
2507                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET,
2508                         struct IssueTicketMessage,
2509                         NULL),
2510  GNUNET_MQ_hd_var_size (consume_ticket_message,
2511                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
2512                         struct ConsumeTicketMessage,
2513                         NULL),
2514  GNUNET_MQ_hd_fixed_size (ticket_iteration_start, 
2515                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
2516                           struct TicketIterationStartMessage,
2517                           NULL),
2518  GNUNET_MQ_hd_fixed_size (ticket_iteration_next, 
2519                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
2520                           struct TicketIterationNextMessage,
2521                           NULL),
2522  GNUNET_MQ_hd_fixed_size (ticket_iteration_stop, 
2523                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
2524                           struct TicketIterationStopMessage,
2525                           NULL),
2526  GNUNET_MQ_hd_var_size (revoke_ticket_message,
2527                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET,
2528                         struct RevokeTicketMessage,
2529                         NULL),
2530  GNUNET_MQ_handler_end());
2531 /* end of gnunet-service-identity-provider.c */