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