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