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