-fix
[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 issue request handle
446  */
447 struct TicketIssueHandle
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    * request id
477    */
478   uint32_t r_id;
479 };
480
481
482 /**
483  * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
484  *
485  */
486 struct EgoEntry
487 {
488   /**
489    * DLL
490    */
491   struct EgoEntry *next;
492
493   /**
494    * DLL
495    */
496   struct EgoEntry *prev;
497
498   /**
499    * Ego handle
500    */
501   struct GNUNET_IDENTITY_Ego *ego;
502
503   /**
504    * Attribute map. Contains the attributes as json_t
505    */
506   struct GNUNET_CONTAINER_MultiHashMap *attr_map;
507
508 };
509
510 /**
511  * Cleanup task
512  */
513 static void
514 cleanup()
515 {
516   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
517               "Cleaning up\n");
518   if (NULL != stats)
519   {
520     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
521     stats = NULL;
522   }
523   GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
524                                               TKT_database)); 
525   GNUNET_free (db_lib_name);
526   db_lib_name = NULL;
527   if (NULL != timeout_task)
528     GNUNET_SCHEDULER_cancel (timeout_task);
529   if (NULL != update_task)
530     GNUNET_SCHEDULER_cancel (update_task);
531   if (NULL != identity_handle)
532     GNUNET_IDENTITY_disconnect (identity_handle);
533   if (NULL != gns_handle)
534     GNUNET_GNS_disconnect (gns_handle);
535   if (NULL != credential_handle)
536     GNUNET_CREDENTIAL_disconnect (credential_handle);
537   if (NULL != ns_it)
538     GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
539   if (NULL != ns_qe)
540     GNUNET_NAMESTORE_cancel (ns_qe);
541   if (NULL != ns_handle)
542     GNUNET_NAMESTORE_disconnect (ns_handle);
543   if (NULL != token)
544     GNUNET_free (token);
545   if (NULL != label)
546     GNUNET_free (label);
547
548 }
549
550 /**
551  * Shutdown task
552  *
553  * @param cls NULL
554  * @param tc task context
555  */
556 static void
557 do_shutdown (void *cls)
558 {
559   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
560               "Shutting down...\n");
561   cleanup();
562 }
563
564 /**
565  * Finished storing newly bootstrapped ABE key
566  */
567 static void
568 bootstrap_store_cont (void *cls,
569                       int32_t success,
570                       const char *emsg)
571 {
572   struct AbeBootstrapHandle *abh = cls;
573   if (GNUNET_SYSERR == success)
574   {
575     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
576                 "Failed to bootstrap ABE master %s\n",
577                 emsg);
578     abh->proc (abh->proc_cls, NULL);
579     GNUNET_free (abh->abe_key);
580     GNUNET_free (abh);
581     return;
582   }
583   abh->proc (abh->proc_cls, abh->abe_key);
584   GNUNET_free (abh);
585 }
586
587 /**
588  * Generates and stores a new ABE key
589  */
590 static void
591 bootstrap_store_task (void *cls)
592 {
593   struct AbeBootstrapHandle *abh = cls;
594   struct GNUNET_GNSRECORD_Data rd[1];
595
596   rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (abh->abe_key,
597                                                               (void**)&rd[0].data);
598   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
599   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
600   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
601   abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
602                                                &abh->identity,
603                                                "+",
604                                                1,
605                                                rd,
606                                                &bootstrap_store_cont,
607                                                abh);
608 }
609
610 /**
611  * Error checking for ABE master
612  */
613 static void
614 bootstrap_abe_error (void *cls)
615 {
616   struct AbeBootstrapHandle *abh = cls;
617   GNUNET_free (abh);
618   abh->proc (abh->proc_cls, NULL);
619   GNUNET_free (abh);
620 }
621
622
623 /**
624  * Handle ABE lookup in namestore
625  */
626 static void
627 bootstrap_abe_result (void *cls,
628                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
629                       const char *label,
630                       unsigned int rd_count,
631                       const struct GNUNET_GNSRECORD_Data *rd)
632 {
633   struct AbeBootstrapHandle *abh = cls;
634   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
635   int i;
636
637   for (i=0;i<rd_count;i++) {
638     if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
639       continue;
640     abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key ((void**)rd[i].data,
641                                                           rd[i].data_size);
642     abh->proc (abh->proc_cls, abe_key);
643     GNUNET_free (abh);
644     return;
645   }
646
647   //No ABE master found, bootstrapping...
648   abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
649   GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
650 }
651
652 /**
653  * Bootstrap ABE master if it does not yet exists.
654  * Will call the AbeBootstrapResult processor when done.
655  */
656 static void
657 bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
658                AbeBootstrapResult proc,
659                void* cls)
660 {
661   struct AbeBootstrapHandle *abh;
662
663   abh = GNUNET_new (struct AbeBootstrapHandle);
664   abh->proc = proc;
665   abh->proc_cls = cls;
666   abh->identity = *identity;
667   abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
668                                                 identity,
669                                                 "+",
670                                                 &bootstrap_abe_error,
671                                                 abh,
672                                                 &bootstrap_abe_result,
673                                                 abh);
674
675 }
676
677
678
679 static int
680 create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
681                          struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
682                          struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
683 {
684   struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
685
686   GNUNET_CRYPTO_hash_to_enc (new_key_hash,
687                              &new_key_hash_str);
688   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
689   static const char ctx_key[] = "gnuid-aes-ctx-key";
690   GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
691                      new_key_hash, sizeof (struct GNUNET_HashCode),
692                      ctx_key, strlen (ctx_key),
693                      NULL, 0);
694   static const char ctx_iv[] = "gnuid-aes-ctx-iv";
695   GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
696                      new_key_hash, sizeof (struct GNUNET_HashCode),
697                      ctx_iv, strlen (ctx_iv),
698                      NULL, 0);
699   return GNUNET_OK;
700 }
701
702 static void
703 cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
704 {
705   if (NULL != handle->attrs)
706     attribute_list_destroy (handle->attrs);
707   if (NULL != handle->ns_qe)
708     GNUNET_NAMESTORE_cancel (handle->ns_qe);
709   GNUNET_free (handle);
710 }
711
712
713 static void
714 send_ticket_result (struct IdpClient *client,
715                     uint32_t r_id,
716                     const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
717 {
718   struct TicketResultMessage *irm;
719   struct GNUNET_MQ_Envelope *env;
720   struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
721
722   /* store ticket in DB */
723   if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
724                                                ticket))
725   {
726     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
727                 "Unable to store ticket after issue\n");
728     GNUNET_break (0);
729   }
730
731   env = GNUNET_MQ_msg_extra (irm,
732                              sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
733                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
734   ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
735   *ticket_buf = *ticket;
736   irm->id = htonl (r_id);
737   GNUNET_MQ_send (client->mq,
738                   env);
739 }
740
741 static void
742 store_ticket_issue_cont (void *cls,
743                          int32_t success,
744                          const char *emsg)
745 {
746   struct TicketIssueHandle *handle = cls;
747
748   handle->ns_qe = NULL;
749   if (GNUNET_SYSERR == success)
750   {
751     cleanup_ticket_issue_handle (handle);
752     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
753                 "Unknown Error\n");
754     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
755     return;
756   }
757   send_ticket_result (handle->client,
758                       handle->r_id,
759                       &handle->ticket);
760   cleanup_ticket_issue_handle (handle);
761 }
762
763
764
765 int
766 serialize_abe_keyinfo2 (const struct TicketIssueHandle *handle,
767                         const struct GNUNET_CRYPTO_AbeKey *rp_key,
768                         struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
769                         char **result)
770 {
771   struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
772   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
773   char *enc_keyinfo;
774   char *serialized_key;
775   char *buf;
776   char *write_ptr;
777   char attrs_str_len;
778   ssize_t size;
779
780   struct GNUNET_CRYPTO_SymmetricSessionKey skey;
781   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
782   struct GNUNET_HashCode new_key_hash;
783   ssize_t enc_size;
784
785   size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key,
786                                             (void**)&serialized_key);
787   attrs_str_len = 0;
788   for (le = handle->attrs->list_head; NULL != le; le = le->next) {
789     attrs_str_len += strlen (le->attribute->name) + 1;
790   }
791   buf = GNUNET_malloc (attrs_str_len + size);
792   write_ptr = buf;
793   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
794               "Writing attributes\n");
795   for (le = handle->attrs->list_head; NULL != le; le = le->next) {
796     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
797                 "%s\n", le->attribute->name);
798
799
800     GNUNET_memcpy (write_ptr,
801                    le->attribute->name,
802                    strlen (le->attribute->name));
803     write_ptr[strlen (le->attribute->name)] = ',';
804     write_ptr += strlen (le->attribute->name) + 1;
805   }
806   write_ptr--;
807   write_ptr[0] = '\0'; //replace last , with a 0-terminator
808   write_ptr++;
809   GNUNET_memcpy (write_ptr,
810                  serialized_key,
811                  size);
812   // ECDH keypair E = eG
813   *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
814   GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
815                                       &ecdh_pubkey);
816   enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
817   // Derived key K = H(eB)
818   GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
819                                                         &handle->ticket.audience,
820                                                         &new_key_hash));
821   create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
822   enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
823                                               size + attrs_str_len,
824                                               &skey, &iv,
825                                               enc_keyinfo);
826   *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
827                            enc_size);
828   GNUNET_memcpy (*result,
829                  &ecdh_pubkey,
830                  sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
831   GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
832                  enc_keyinfo,
833                  enc_size);
834   GNUNET_free (enc_keyinfo);
835   return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
836 }
837
838
839
840 static void
841 issue_ticket_after_abe_bootstrap (void *cls,
842                                   struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
843 {
844   struct TicketIssueHandle *ih = cls;
845   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
846   struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
847   struct GNUNET_GNSRECORD_Data code_record[1];
848   struct GNUNET_CRYPTO_AbeKey *rp_key;
849   char *code_record_data;
850   char **attrs;
851   char *label;
852   int attrs_len;
853   int i;
854   size_t code_record_len;
855
856   //Create new ABE key for RP
857   attrs_len = 0;
858   for (le = ih->attrs->list_head; NULL != le; le = le->next)
859     attrs_len++;
860   attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
861   i = 0;
862   for (le = ih->attrs->list_head; NULL != le; le = le->next) {
863     attrs[i] = (char*) le->attribute->name;
864     i++;
865   }
866   attrs[i] = NULL;
867   rp_key = GNUNET_CRYPTO_cpabe_create_key (abe_key,
868                                            attrs);
869
870   //TODO review this wireformat
871   code_record_len = serialize_abe_keyinfo2 (ih,
872                                             rp_key,
873                                             &ecdhe_privkey,
874                                             &code_record_data);
875   code_record[0].data = code_record_data;
876   code_record[0].data_size = code_record_len;
877   code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
878   code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
879   code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
880
881   label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
882                                                sizeof (uint64_t));
883   //Publish record
884   ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
885                                               &ih->identity,
886                                               label,
887                                               1,
888                                               code_record,
889                                               &store_ticket_issue_cont,
890                                               ih);
891   GNUNET_free (ecdhe_privkey);
892   GNUNET_free (label);
893   GNUNET_free (attrs);
894   GNUNET_free (code_record_data);
895 }
896
897
898 /**
899  * Checks a ticket issue message
900  *
901  * @param cls client sending the message
902  * @param im message of type `struct TicketIssueMessage`
903  * @return #GNUNET_OK if @a im is well-formed
904  */
905 static int
906 check_ticket_issue_message(void *cls,
907                            const struct TicketIssueMessage *im)
908 {
909   uint16_t size;
910
911   size = ntohs (im->header.size);
912   if (size <= sizeof (struct TicketIssueMessage))
913   {
914     GNUNET_break (0);
915     return GNUNET_SYSERR;
916   }
917   return GNUNET_OK;
918 }
919
920
921 /**
922  *
923  * Handler for ticket issue message
924  *
925  * @param cls unused
926  * @param client who sent the message
927  * @param message the message
928  */
929 static void
930 handle_ticket_issue_message (void *cls,
931                              const struct TicketIssueMessage *im)
932 {
933   struct TicketIssueHandle *ih;
934   struct IdpClient *idp = cls;
935   size_t attrs_len;
936
937   ih = GNUNET_new (struct TicketIssueHandle);
938   attrs_len = ntohs (im->attr_len);
939   ih->attrs = attribute_list_deserialize ((char*)&im[1], attrs_len);
940   ih->r_id = ntohl (im->id);
941   ih->client = idp;
942   ih->identity = im->identity;
943   GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
944                                       &ih->ticket.identity);
945   ih->ticket.audience = im->rp;
946   ih->ticket.rnd =
947     GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
948                               UINT64_MAX);
949   bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih);
950   GNUNET_SERVICE_client_continue (idp->client);
951
952 }
953
954
955
956 static void
957 cleanup_as_handle (struct AttributeStoreHandle *handle)
958 {
959   if (NULL != handle->attribute)
960     GNUNET_free (handle->attribute);
961   if (NULL != handle->abe_key)
962     GNUNET_free (handle->abe_key);
963   GNUNET_free (handle);
964 }
965
966 /**
967  * Checks a ticket consume message
968  *
969  * @param cls client sending the message
970  * @param im message of type `struct ConsumeTicketMessage`
971  * @return #GNUNET_OK if @a im is well-formed
972  */
973 static int
974 check_consume_ticket_message(void *cls,
975                              const struct ConsumeTicketMessage *cm)
976 {
977   uint16_t size;
978
979   size = ntohs (cm->header.size);
980   if (size <= sizeof (struct ConsumeTicketMessage))
981   {
982     GNUNET_break (0);
983     return GNUNET_SYSERR;
984   }
985   return GNUNET_OK;
986 }
987
988 static void
989 process_parallel_lookup2 (void *cls, uint32_t rd_count,
990                           const struct GNUNET_GNSRECORD_Data *rd)
991 {
992   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
993               "Parallel lookup finished (count=%u)\n", rd_count);
994   struct ParallelLookup *parallel_lookup = cls;
995   struct ConsumeTicketHandle *handle = parallel_lookup->handle;
996   struct ConsumeTicketResultMessage *crm;
997   struct GNUNET_MQ_Envelope *env;
998   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *attr_le;
999   char *data;
1000   char *data_tmp;
1001   size_t attr_len;
1002   size_t attrs_len;
1003
1004   GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1005                                handle->parallel_lookups_tail,
1006                                parallel_lookup);
1007   GNUNET_free (parallel_lookup->label);
1008   GNUNET_free (parallel_lookup);
1009   if (1 != rd_count)
1010     GNUNET_break(0);//TODO
1011   if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1012   {
1013     attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
1014                                             rd->data_size,
1015                                             handle->key,
1016                                             (void**)&data);
1017     attr_le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
1018     attr_le->attribute = attribute_deserialize (data,
1019                                                 attr_len);
1020     GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
1021                                  handle->attrs->list_tail,
1022                                  attr_le);
1023     GNUNET_free (data);
1024   }
1025   if (NULL != handle->parallel_lookups_head)
1026     return; //Wait for more
1027   /* Else we are done */
1028
1029   /* Store ticket in DB */
1030   if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1031                                                &handle->ticket))
1032   {
1033     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1034                 "Unable to store ticket after consume\n");
1035     GNUNET_break (0);
1036   }
1037   
1038   GNUNET_SCHEDULER_cancel (handle->kill_task);
1039   attrs_len = attribute_list_serialize_get_size (handle->attrs);
1040   env = GNUNET_MQ_msg_extra (crm,
1041                              attrs_len,
1042                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
1043   crm->id = htonl (handle->r_id);
1044   crm->attrs_len = htons (attrs_len);
1045   crm->identity = handle->ticket.identity;
1046   data_tmp = (char *) &crm[1];
1047   attribute_list_serialize (handle->attrs,
1048                             data_tmp);
1049   GNUNET_MQ_send (handle->client->mq, env);
1050 }
1051
1052 void
1053 abort_parallel_lookups2 (void *cls)
1054 {
1055   struct ConsumeTicketHandle *handle = cls;
1056   struct ParallelLookup *lu;
1057   struct ParallelLookup *tmp;
1058   struct AttributeResultMessage *arm;
1059   struct GNUNET_MQ_Envelope *env;
1060
1061   for (lu = handle->parallel_lookups_head;
1062        NULL != lu;) {
1063     GNUNET_GNS_lookup_cancel (lu->lookup_request);
1064     GNUNET_free (lu->label);
1065     tmp = lu->next;
1066     GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1067                                  handle->parallel_lookups_tail,
1068                                  lu);
1069     GNUNET_free (lu);
1070     lu = tmp;
1071   }
1072   env = GNUNET_MQ_msg (arm,
1073                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1074   arm->id = htonl (handle->r_id);
1075   arm->attr_len = htons (0);
1076   GNUNET_MQ_send (handle->client->mq, env);
1077
1078 }
1079
1080 static void
1081 cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
1082 {
1083   if (NULL != handle->key)
1084     GNUNET_free (handle->key);
1085   GNUNET_free (handle);
1086 }
1087
1088
1089 static void
1090 process_consume_abe_key (void *cls, uint32_t rd_count,
1091                          const struct GNUNET_GNSRECORD_Data *rd)
1092 {
1093   struct ConsumeTicketHandle *handle = cls;
1094   struct GNUNET_HashCode new_key_hash;
1095   struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1096   struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1097   struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1098   struct ParallelLookup *parallel_lookup;
1099   size_t size;
1100   char *buf;
1101   char *scope;
1102   char *lookup_query;
1103
1104   handle->lookup_request = NULL;
1105   if (1 != rd_count)
1106   {
1107     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1108                 "Number of keys %d != 1.",
1109                 rd_count);
1110     cleanup_consume_ticket_handle (handle);
1111     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1112     return;
1113   }
1114
1115   //Decrypt
1116   ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1117
1118   buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1119
1120   //Calculate symmetric key from ecdh parameters
1121   GNUNET_assert (GNUNET_OK == 
1122                  GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
1123                                            ecdh_key,
1124                                            &new_key_hash));
1125   create_sym_key_from_ecdh (&new_key_hash,
1126                             &enc_key,
1127                             &enc_iv);
1128   size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1129                                           rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1130                                           &enc_key,
1131                                           &enc_iv,
1132                                           buf);
1133
1134   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1135               "Decrypted bytes: %zd Expected bytes: %zd\n",
1136               size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1137
1138   scopes = GNUNET_strdup (buf);
1139   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1140               "Scopes %s\n", scopes);
1141   handle->key = GNUNET_CRYPTO_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1142                                                      rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1143                                                      - strlen (scopes) - 1);
1144
1145   for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1146   {
1147     GNUNET_asprintf (&lookup_query,
1148                      "%s.gnu",
1149                      scope);
1150     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1151                 "Looking up %s\n", lookup_query);
1152     parallel_lookup = GNUNET_new (struct ParallelLookup);
1153     parallel_lookup->handle = handle;
1154     parallel_lookup->label = GNUNET_strdup (scope);
1155     parallel_lookup->lookup_request
1156       = GNUNET_GNS_lookup (gns_handle,
1157                            lookup_query,
1158                            &handle->ticket.identity,
1159                            GNUNET_GNSRECORD_TYPE_ID_ATTR,
1160                            GNUNET_GNS_LO_LOCAL_MASTER,
1161                            &process_parallel_lookup2,
1162                            parallel_lookup);
1163     GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1164                                  handle->parallel_lookups_tail,
1165                                  parallel_lookup);
1166     GNUNET_free (lookup_query);
1167   }
1168   handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1169                                                     &abort_parallel_lookups2,
1170                                                     handle);
1171 }
1172
1173
1174 /**
1175  *
1176  * Handler for ticket issue message
1177  *
1178  * @param cls unused
1179  * @param client who sent the message
1180  * @param message the message
1181  */
1182 static void
1183 handle_consume_ticket_message (void *cls,
1184                                const struct ConsumeTicketMessage *cm)
1185 {
1186   struct ConsumeTicketHandle *ch;
1187   struct IdpClient *idp = cls;
1188   char* lookup_query;
1189   char* rnd_label;
1190
1191   ch = GNUNET_new (struct ConsumeTicketHandle);
1192   ch->r_id = ntohl (cm->id);
1193   ch->client = idp;
1194   ch->identity = cm->identity;
1195   ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
1196   GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
1197                                       &ch->identity_pub);
1198   ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
1199   rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
1200                                                    sizeof (uint64_t));
1201   GNUNET_asprintf (&lookup_query,
1202                    "%s.gnu",
1203                    rnd_label);
1204   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1205               "Looking for ABE key under %s\n", lookup_query);
1206
1207   ch->lookup_request
1208     = GNUNET_GNS_lookup (gns_handle,
1209                          lookup_query,
1210                          &ch->ticket.identity,
1211                          GNUNET_GNSRECORD_TYPE_ABE_KEY,
1212                          GNUNET_GNS_LO_LOCAL_MASTER,
1213                          &process_consume_abe_key,
1214                          ch);
1215   GNUNET_free (rnd_label);
1216   GNUNET_free (lookup_query);
1217   GNUNET_SERVICE_client_continue (idp->client);
1218 }
1219
1220 void
1221 attr_store_cont (void *cls,
1222                  int32_t success,
1223                  const char *emsg)
1224 {
1225   struct AttributeStoreHandle *as_handle = cls;
1226   struct GNUNET_MQ_Envelope *env;
1227   struct AttributeStoreResponseMessage *acr_msg;
1228
1229   if (GNUNET_SYSERR == success)
1230   {
1231     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1232                 "Failed to store attribute %s\n",
1233                 emsg);
1234     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1235     return;
1236   }
1237
1238   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1239               "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1240   env = GNUNET_MQ_msg (acr_msg,
1241                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
1242   acr_msg->id = htonl (as_handle->r_id);
1243   acr_msg->op_result = htonl (GNUNET_OK);
1244   GNUNET_MQ_send (as_handle->client->mq,
1245                   env);
1246   cleanup_as_handle (as_handle);
1247 }
1248
1249 static void
1250 attr_store_task (void *cls)
1251 {
1252   struct AttributeStoreHandle *as_handle = cls;
1253   struct GNUNET_GNSRECORD_Data rd[1];
1254   char* buf;
1255   size_t buf_size;
1256
1257   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1258               "Storing attribute\n");
1259   buf_size = attribute_serialize_get_size (as_handle->attribute);
1260   buf = GNUNET_malloc (buf_size);
1261
1262   attribute_serialize (as_handle->attribute,
1263                        buf);
1264
1265   /**
1266    * Encrypt the attribute value and store in namestore
1267    */
1268   rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1269                                                  buf_size,
1270                                                  as_handle->attribute->name, //Policy
1271                                                  as_handle->abe_key,
1272                                                  (void**)&rd[0].data);
1273   GNUNET_free (buf);
1274   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1275   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1276   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1277   as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1278                                                      &as_handle->identity,
1279                                                      as_handle->attribute->name,
1280                                                      1,
1281                                                      rd,
1282                                                      &attr_store_cont,
1283                                                      as_handle);
1284   GNUNET_free ((void*)rd[0].data);
1285
1286 }
1287
1288
1289 static void
1290 store_after_abe_bootstrap (void *cls,
1291                            struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1292 {
1293   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1294               "Finished ABE bootstrap\n");
1295   struct AttributeStoreHandle *ash = cls;
1296   ash->abe_key = abe_key;
1297   GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1298 }
1299
1300 /**
1301  * Checks a store message
1302  *
1303  * @param cls client sending the message
1304  * @param sam message of type `struct AttributeStoreMessage`
1305  * @return #GNUNET_OK if @a im is well-formed
1306  */
1307 static int
1308 check_attribute_store_message(void *cls,
1309                               const struct AttributeStoreMessage *sam)
1310 {
1311   uint16_t size;
1312
1313   size = ntohs (sam->header.size);
1314   if (size <= sizeof (struct AttributeStoreMessage))
1315   {
1316     GNUNET_break (0);
1317     return GNUNET_SYSERR;
1318   }
1319   return GNUNET_OK;
1320 }
1321
1322
1323 /**
1324  *
1325  * Handler for store message
1326  *
1327  * @param cls unused
1328  * @param client who sent the message
1329  * @param message the message
1330  */
1331 static void
1332 handle_attribute_store_message (void *cls,
1333                                 const struct AttributeStoreMessage *sam)
1334 {
1335   struct AttributeStoreHandle *as_handle;
1336   struct IdpClient *idp = cls;
1337   size_t data_len;
1338   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1339               "Received ATTRIBUTE_STORE message\n");
1340
1341   data_len = ntohs (sam->attr_len);
1342
1343   as_handle = GNUNET_new (struct AttributeStoreHandle);
1344   as_handle->attribute = attribute_deserialize ((char*)&sam[1],
1345                                                 data_len);
1346
1347   as_handle->r_id = ntohl (sam->id);
1348   as_handle->identity = sam->identity;
1349   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1350                                       &as_handle->identity_pkey);
1351
1352   GNUNET_SERVICE_client_continue (idp->client);
1353   as_handle->client = idp;
1354   bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle);
1355 }
1356
1357 static void
1358 cleanup_iter_handle (struct AttributeIterator *ai)
1359 {
1360   if (NULL != ai->abe_key)
1361     GNUNET_free (ai->abe_key);
1362   GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
1363                                ai->client->op_tail,
1364                                ai);
1365   GNUNET_free (ai);
1366 }
1367
1368 static void
1369 attr_iter_error (void *cls)
1370 {
1371   //struct AttributeIterator *ai = cls;
1372   //TODO
1373   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1374               "Failed to iterate over attributes\n");
1375   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1376 }
1377
1378 static void
1379 attr_iter_finished (void *cls)
1380 {
1381   struct AttributeIterator *ai = cls;
1382   struct GNUNET_MQ_Envelope *env;
1383   struct AttributeResultMessage *arm;
1384
1385   env = GNUNET_MQ_msg (arm,
1386                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1387   arm->id = htonl (ai->request_id);
1388   arm->attr_len = htons (0);
1389   GNUNET_MQ_send (ai->client->mq, env);
1390   cleanup_iter_handle (ai);
1391 }
1392
1393 static void
1394 attr_iter_cb (void *cls,
1395               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1396               const char *label,
1397               unsigned int rd_count,
1398               const struct GNUNET_GNSRECORD_Data *rd)
1399 {
1400   struct AttributeIterator *ai = cls;
1401   struct AttributeResultMessage *arm;
1402   struct GNUNET_CRYPTO_AbeKey *key;
1403   struct GNUNET_MQ_Envelope *env;
1404   ssize_t msg_extra_len;
1405   char* attr_ser;
1406   char* attrs[2];
1407   char* data_tmp;
1408
1409   if (rd_count != 1)
1410   {
1411     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1412     return;
1413   }
1414
1415   if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
1416     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1417     return;
1418   }
1419   attrs[0] = (char*)label;
1420   attrs[1] = 0;
1421   key = GNUNET_CRYPTO_cpabe_create_key (ai->abe_key,
1422                                         attrs);
1423   msg_extra_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
1424                                                rd->data_size,
1425                                                key,
1426                                                (void**)&attr_ser);
1427   GNUNET_CRYPTO_cpabe_delete_key (key);
1428   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1429               "Found attribute: %s\n", label);
1430   env = GNUNET_MQ_msg_extra (arm,
1431                              msg_extra_len,
1432                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1433   arm->id = htonl (ai->request_id);
1434   arm->attr_len = htons (msg_extra_len);
1435   GNUNET_CRYPTO_ecdsa_key_get_public (zone,
1436                                       &arm->identity);
1437   data_tmp = (char *) &arm[1];
1438   GNUNET_memcpy (data_tmp,
1439                  attr_ser,
1440                  msg_extra_len);
1441   GNUNET_MQ_send (ai->client->mq, env);
1442   GNUNET_free (attr_ser);
1443 }
1444
1445
1446 void
1447 iterate_after_abe_bootstrap (void *cls,
1448                              struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1449 {
1450   struct AttributeIterator *ai = cls;
1451   ai->abe_key = abe_key;
1452   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1453                                                      &ai->identity,
1454                                                      &attr_iter_error,
1455                                                      ai,
1456                                                      &attr_iter_cb,
1457                                                      ai,
1458                                                      &attr_iter_finished,
1459                                                      ai);
1460 }
1461
1462
1463 /**
1464  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_START message
1465  *
1466  * @param cls the client sending the message
1467  * @param zis_msg message from the client
1468  */
1469 static void
1470 handle_iteration_start (void *cls,
1471                         const struct AttributeIterationStartMessage *ais_msg)
1472 {
1473   struct IdpClient *idp = cls;
1474   struct AttributeIterator *ai;
1475
1476   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1477               "Received ATTRIBUTE_ITERATION_START message\n");
1478   ai = GNUNET_new (struct AttributeIterator);
1479   ai->request_id = ntohl (ais_msg->id);
1480   ai->client = idp;
1481   ai->identity = ais_msg->identity;
1482
1483   GNUNET_CONTAINER_DLL_insert (idp->op_head,
1484                                idp->op_tail,
1485                                ai);
1486   bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai);
1487   GNUNET_SERVICE_client_continue (idp->client);
1488 }
1489
1490
1491 /**
1492  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_STOP message
1493  *
1494  * @param cls the client sending the message
1495  * @param ais_msg message from the client
1496  */
1497 static void
1498 handle_iteration_stop (void *cls,
1499                        const struct AttributeIterationStopMessage *ais_msg)
1500 {
1501   struct IdpClient *idp = cls;
1502   struct AttributeIterator *ai;
1503   uint32_t rid;
1504
1505   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1506               "Received `%s' message\n",
1507               "ATTRIBUTE_ITERATION_STOP");
1508   rid = ntohl (ais_msg->id);
1509   for (ai = idp->op_head; NULL != ai; ai = ai->next)
1510     if (ai->request_id == rid)
1511       break;
1512   if (NULL == ai)
1513   {
1514     GNUNET_break (0);
1515     GNUNET_SERVICE_client_drop (idp->client);
1516     return;
1517   }
1518   GNUNET_CONTAINER_DLL_remove (idp->op_head,
1519                                idp->op_tail,
1520                                ai);
1521   GNUNET_free (ai);
1522   GNUNET_SERVICE_client_continue (idp->client);
1523 }
1524
1525
1526 /**
1527  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT message
1528  *
1529  * @param cls the client sending the message
1530  * @param message message from the client
1531  */
1532 static void
1533 handle_iteration_next (void *cls,
1534                        const struct AttributeIterationNextMessage *ais_msg)
1535 {
1536   struct IdpClient *idp = cls;
1537   struct AttributeIterator *ai;
1538   uint32_t rid;
1539
1540   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1541               "Received ATTRIBUTE_ITERATION_NEXT message\n");
1542   rid = ntohl (ais_msg->id);
1543   for (ai = idp->op_head; NULL != ai; ai = ai->next)
1544     if (ai->request_id == rid)
1545       break;
1546   if (NULL == ai)
1547   {
1548     GNUNET_break (0);
1549     GNUNET_SERVICE_client_drop (idp->client);
1550     return;
1551   }
1552   GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1553   GNUNET_SERVICE_client_continue (idp->client);
1554 }
1555
1556 /**
1557  * Ticket iteration processor result
1558  */
1559 enum ZoneIterationResult
1560 {
1561   /**
1562    * Iteration start.
1563    */
1564   IT_START = 0,
1565
1566   /**
1567    * Found tickets,
1568    * Continue to iterate with next iteration_next call
1569    */
1570   IT_SUCCESS_MORE_AVAILABLE = 1,
1571
1572   /**
1573    * Iteration complete
1574    */
1575   IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
1576 };
1577
1578
1579 /**
1580  * Context for ticket iteration
1581  */
1582 struct TicketIterationProcResult
1583 {
1584   /**
1585    * The ticket iteration handle
1586    */
1587   struct TicketIteration *ti;
1588
1589   /**
1590    * Iteration result: iteration done?
1591    * #IT_SUCCESS_MORE_AVAILABLE:  if there may be more results overall but
1592    * we got one for now and have sent it to the client
1593    * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
1594    * #IT_START: if we are still trying to find a result.
1595    */
1596   int res_iteration_finished;
1597
1598 };
1599
1600
1601
1602 /**
1603  * Process ticket from database
1604  *
1605  * @param cls struct TicketIterationProcResult
1606  * @param ticket the ticket
1607  * @param attrs the attributes
1608  */
1609 static void
1610 ticket_iterate_proc (void *cls,
1611                      const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
1612 {
1613   struct TicketIterationProcResult *proc = cls;
1614
1615   if (NULL == ticket)
1616   {
1617     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1618                 "Iteration done\n");
1619     proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
1620     return;
1621   }
1622   proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
1623   send_ticket_result (proc->ti->client,
1624                       proc->ti->r_id,
1625                       ticket);
1626
1627 }
1628
1629 /**
1630  * Perform ticket iteration step
1631  *
1632  * @param ti ticket iterator to process
1633  */
1634 static void
1635 run_ticket_iteration_round (struct TicketIteration *ti)
1636 {
1637   struct TicketIterationProcResult proc;
1638   struct GNUNET_MQ_Envelope *env;
1639   struct TicketResultMessage *trm;
1640   int ret;
1641
1642   memset (&proc, 0, sizeof (proc));
1643   proc.ti = ti;
1644   proc.res_iteration_finished = IT_START;
1645   while (IT_START == proc.res_iteration_finished)
1646   {
1647     if (GNUNET_SYSERR ==
1648         (ret = TKT_database->iterate_tickets (TKT_database->cls,
1649                                               &ti->identity,
1650                                               ti->is_audience,
1651                                               ti->offset,
1652                                               &ticket_iterate_proc,
1653                                               &proc)))
1654     {
1655       GNUNET_break (0);
1656       break;
1657     }
1658     if (GNUNET_NO == ret)
1659       proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
1660     ti->offset++;
1661   }
1662   if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
1663   {
1664     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1665                 "More results available\n");
1666     return; /* more later */
1667   }
1668   /* send empty response to indicate end of list */
1669   env = GNUNET_MQ_msg (trm,
1670                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
1671   trm->id = htonl (ti->r_id);
1672   GNUNET_MQ_send (ti->client->mq,
1673                   env);
1674   GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
1675                                ti->client->ticket_iter_tail,
1676                                ti);
1677   GNUNET_free (ti);
1678 }
1679
1680 /**
1681  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START message
1682  *
1683  * @param cls the client sending the message
1684  * @param tis_msg message from the client
1685  */
1686 static void
1687 handle_ticket_iteration_start (void *cls,
1688                                const struct TicketIterationStartMessage *tis_msg)
1689 {
1690   struct IdpClient *client = cls;
1691   struct TicketIteration *ti;
1692
1693   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1694               "Received TICKET_ITERATION_START message\n");
1695   ti = GNUNET_new (struct TicketIteration);
1696   ti->r_id = ntohl (tis_msg->id);
1697   ti->offset = 0;
1698   ti->client = client;
1699   ti->identity = tis_msg->identity;
1700   ti->is_audience = ntohl (tis_msg->is_audience);
1701
1702   GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
1703                                client->ticket_iter_tail,
1704                                ti);
1705   run_ticket_iteration_round (ti);
1706   GNUNET_SERVICE_client_continue (client->client);
1707 }
1708
1709
1710 /**
1711  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP message
1712  *
1713  * @param cls the client sending the message
1714  * @param tis_msg message from the client
1715  */
1716 static void
1717 handle_ticket_iteration_stop (void *cls,
1718                               const struct TicketIterationStopMessage *tis_msg)
1719 {
1720   struct IdpClient *client = cls;
1721   struct TicketIteration *ti;
1722   uint32_t rid;
1723
1724   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1725               "Received `%s' message\n",
1726               "TICKET_ITERATION_STOP");
1727   rid = ntohl (tis_msg->id);
1728   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1729     if (ti->r_id == rid)
1730       break;
1731   if (NULL == ti)
1732   {
1733     GNUNET_break (0);
1734     GNUNET_SERVICE_client_drop (client->client);
1735     return;
1736   }
1737   GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
1738                                client->ticket_iter_tail,
1739                                ti);
1740   GNUNET_free (ti);
1741   GNUNET_SERVICE_client_continue (client->client);
1742 }
1743
1744
1745 /**
1746  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT message
1747  *
1748  * @param cls the client sending the message
1749  * @param message message from the client
1750  */
1751 static void
1752 handle_ticket_iteration_next (void *cls,
1753                               const struct TicketIterationNextMessage *tis_msg)
1754 {
1755   struct IdpClient *client = cls;
1756   struct TicketIteration *ti;
1757   uint32_t rid;
1758
1759   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1760               "Received TICKET_ITERATION_NEXT message\n");
1761   rid = ntohl (tis_msg->id);
1762   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1763     if (ti->r_id == rid)
1764       break;
1765   if (NULL == ti)
1766   {
1767     GNUNET_break (0);
1768     GNUNET_SERVICE_client_drop (client->client);
1769     return;
1770   }
1771   run_ticket_iteration_round (ti);
1772   GNUNET_SERVICE_client_continue (client->client);
1773 }
1774
1775
1776
1777
1778 /**
1779  * Main function that will be run
1780  *
1781  * @param cls closure
1782  * @param args remaining command-line arguments
1783  * @param cfgfile name of the configuration file used (for saving, can be NULL)
1784  * @param c configuration
1785  */
1786 static void
1787 run (void *cls,
1788      const struct GNUNET_CONFIGURATION_Handle *c,
1789      struct GNUNET_SERVICE_Handle *server)
1790 {
1791   char *database;
1792   cfg = c;
1793
1794   stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
1795
1796   //Connect to identity and namestore services
1797   ns_handle = GNUNET_NAMESTORE_connect (cfg);
1798   if (NULL == ns_handle)
1799   {
1800     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
1801   }
1802
1803   gns_handle = GNUNET_GNS_connect (cfg);
1804   if (NULL == gns_handle)
1805   {
1806     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1807   }
1808   credential_handle = GNUNET_CREDENTIAL_connect (cfg);
1809   if (NULL == credential_handle)
1810   {
1811     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
1812   }
1813   identity_handle = GNUNET_IDENTITY_connect (cfg,
1814                                              NULL,
1815                                              NULL);
1816
1817   /* Loading DB plugin */
1818   if (GNUNET_OK !=
1819       GNUNET_CONFIGURATION_get_value_string (cfg,
1820                                              "identity-provider",
1821                                              "database",
1822                                              &database))
1823     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1824                 "No database backend configured\n");
1825   GNUNET_asprintf (&db_lib_name,
1826                    "libgnunet_plugin_identity_provider_%s",
1827                    database);
1828   TKT_database = GNUNET_PLUGIN_load (db_lib_name,
1829                                      (void *) cfg);
1830   GNUNET_free (database);
1831   if (NULL == TKT_database)
1832   {
1833     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1834                 "Could not load database backend `%s'\n",
1835                 db_lib_name);
1836     GNUNET_SCHEDULER_shutdown ();
1837     return;
1838   }
1839
1840   if (GNUNET_OK ==
1841       GNUNET_CONFIGURATION_get_value_time (cfg,
1842                                            "identity-provider",
1843                                            "TOKEN_EXPIRATION_INTERVAL",
1844                                            &token_expiration_interval))
1845   {
1846     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1847                 "Time window for zone iteration: %s\n",
1848                 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
1849                                                         GNUNET_YES));
1850   } else {
1851     token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
1852   }
1853
1854   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1855 }
1856
1857 /**
1858  * Called whenever a client is disconnected.
1859  *
1860  * @param cls closure
1861  * @param client identification of the client
1862  * @param app_ctx @a client
1863  */
1864 static void
1865 client_disconnect_cb (void *cls,
1866                       struct GNUNET_SERVICE_Client *client,
1867                       void *app_ctx)
1868 {
1869   struct IdpClient *idp = app_ctx;
1870   struct AttributeIterator *ai;
1871
1872   //TODO other operations
1873
1874   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1875               "Client %p disconnected\n",
1876               client);
1877
1878   while (NULL != (ai = idp->op_head))
1879   {
1880     GNUNET_CONTAINER_DLL_remove (idp->op_head,
1881                                  idp->op_tail,
1882                                  ai);
1883     GNUNET_free (ai);
1884   }
1885   GNUNET_free (idp);
1886 }
1887
1888
1889 /**
1890  * Add a client to our list of active clients.
1891  *
1892  * @param cls NULL
1893  * @param client client to add
1894  * @param mq message queue for @a client
1895  * @return internal namestore client structure for this client
1896  */
1897 static void *
1898 client_connect_cb (void *cls,
1899                    struct GNUNET_SERVICE_Client *client,
1900                    struct GNUNET_MQ_Handle *mq)
1901 {
1902   struct IdpClient *idp;
1903   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1904               "Client %p connected\n",
1905               client);
1906   idp = GNUNET_new (struct IdpClient);
1907   idp->client = client;
1908   idp->mq = mq;
1909   return idp;
1910 }
1911
1912
1913
1914 /**
1915  * Define "main" method using service macro.
1916  */
1917 GNUNET_SERVICE_MAIN
1918 ("identity-provider",
1919  GNUNET_SERVICE_OPTION_NONE,
1920  &run,
1921  &client_connect_cb,
1922  &client_disconnect_cb,
1923  NULL,
1924  GNUNET_MQ_hd_var_size (attribute_store_message,
1925                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
1926                         struct AttributeStoreMessage,
1927                         NULL),
1928  GNUNET_MQ_hd_fixed_size (iteration_start, 
1929                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
1930                           struct AttributeIterationStartMessage,
1931                           NULL),
1932  GNUNET_MQ_hd_fixed_size (iteration_next, 
1933                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
1934                           struct AttributeIterationNextMessage,
1935                           NULL),
1936  GNUNET_MQ_hd_fixed_size (iteration_stop, 
1937                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
1938                           struct AttributeIterationStopMessage,
1939                           NULL),
1940  GNUNET_MQ_hd_var_size (ticket_issue_message,
1941                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE,
1942                         struct TicketIssueMessage,
1943                         NULL),
1944  GNUNET_MQ_hd_var_size (consume_ticket_message,
1945                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
1946                         struct ConsumeTicketMessage,
1947                         NULL),
1948  GNUNET_MQ_hd_fixed_size (ticket_iteration_start, 
1949                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
1950                           struct TicketIterationStartMessage,
1951                           NULL),
1952  GNUNET_MQ_hd_fixed_size (ticket_iteration_next, 
1953                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
1954                           struct TicketIterationNextMessage,
1955                           NULL),
1956  GNUNET_MQ_hd_fixed_size (ticket_iteration_stop, 
1957                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
1958                           struct TicketIterationStopMessage,
1959                           NULL),
1960
1961  GNUNET_MQ_handler_end());
1962  /* end of gnunet-service-identity-provider.c */