c8ae8a2385958011f4886ba198504ca9f8241c39
[oweals/gnunet.git] / src / reclaim / gnunet-service-reclaim.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 it
6    under the terms of the GNU Affero General Public License as published
7    by the Free Software Foundation, either version 3 of the License,
8    or (at your 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    Affero General Public License for more details.
14
15    You should have received a copy of the GNU Affero General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18    SPDX-License-Identifier: AGPL3.0-or-later
19    */
20 /**
21  * @author Martin Schanzenbach
22  * @file src/reclaim/gnunet-service-reclaim.c
23  * @brief reclaim 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_reclaim_plugin.h"
34 #include "gnunet_reclaim_attribute_lib.h"
35 #include "gnunet_signatures.h"
36 #include "gnunet-service-reclaim_tickets.h"
37 #include "reclaim.h"
38
39 /**
40  * First pass state
41  */
42 #define STATE_INIT 0
43
44 /**
45  * Normal operation state
46  */
47 #define STATE_POST_INIT 1
48
49 /**
50  * Minimum interval between updates
51  */
52 #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
53
54 /**
55  * Standard token expiration time
56  */
57 #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
58
59 /**
60  * Identity handle
61  */
62 static struct GNUNET_IDENTITY_Handle *identity_handle;
63
64 /**
65  * Database handle
66  */
67 static struct GNUNET_RECLAIM_PluginFunctions *TKT_database;
68
69 /**
70  * Name of DB plugin
71  */
72 static char *db_lib_name;
73
74 /**
75  * Token expiration interval
76  */
77 static struct GNUNET_TIME_Relative token_expiration_interval;
78
79 /**
80  * Namestore handle
81  */
82 static struct GNUNET_NAMESTORE_Handle *nsh;
83
84 /**
85  * Timeout task
86  */
87 static struct GNUNET_SCHEDULER_Task *timeout_task;
88
89 /**
90  * Update task
91  */
92 static struct GNUNET_SCHEDULER_Task *update_task;
93
94
95 /**
96  * Our configuration.
97  */
98 static const struct GNUNET_CONFIGURATION_Handle *cfg;
99
100 /**
101  * An idp client
102  */
103 struct IdpClient;
104
105 /**
106  * A ticket iteration operation.
107  */
108 struct TicketIteration
109 {
110   /**
111    * DLL
112    */
113   struct TicketIteration *next;
114
115   /**
116    * DLL
117    */
118   struct TicketIteration *prev;
119
120   /**
121    * Client which intiated this zone iteration
122    */
123   struct IdpClient *client;
124
125   /**
126    * The operation id fot the iteration in the response for the client
127    */
128   uint32_t r_id;
129
130   /**
131    * The ticket iterator
132    */
133   struct RECLAIM_TICKETS_Iterator *iter;
134 };
135
136
137 /**
138  * An attribute iteration operation.
139  */
140 struct AttributeIterator
141 {
142   /**
143    * Next element in the DLL
144    */
145   struct AttributeIterator *next;
146
147   /**
148    * Previous element in the DLL
149    */
150   struct AttributeIterator *prev;
151
152   /**
153    * IDP client which intiated this zone iteration
154    */
155   struct IdpClient *client;
156
157   /**
158    * Key of the zone we are iterating over.
159    */
160   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
161
162   /**
163    * Namestore iterator
164    */
165   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
166
167   /**
168    * The operation id fot the zone iteration in the response for the client
169    */
170   uint32_t request_id;
171
172 };
173
174
175
176 /**
177  * An idp client
178  */
179 struct IdpClient
180 {
181
182   /**
183    * The client
184    */
185   struct GNUNET_SERVICE_Client *client;
186
187   /**
188    * Message queue for transmission to @e client
189    */
190   struct GNUNET_MQ_Handle *mq;
191
192   /**
193    * Head of the DLL of
194    * Attribute iteration operations in
195    * progress initiated by this client
196    */
197   struct AttributeIterator *attr_iter_head;
198
199   /**
200    * Tail of the DLL of
201    * Attribute iteration operations
202    * in progress initiated by this client
203    */
204   struct AttributeIterator *attr_iter_tail;
205
206   /**
207    * Head of DLL of ticket iteration ops
208    */
209   struct TicketIteration *ticket_iter_head;
210
211   /**
212    * Tail of DLL of ticket iteration ops
213    */
214   struct TicketIteration *ticket_iter_tail;
215
216   /**
217    * Head of DLL of ticket revocation ops
218    */
219   struct TicketRevocationHandle *revoke_op_head;
220
221   /**
222    * Tail of DLL of ticket revocation ops
223    */
224   struct TicketRevocationHandle *revoke_op_tail;
225
226   /**
227    * Head of DLL of ticket issue ops
228    */
229   struct TicketIssueOperation *issue_op_head;
230
231   /**
232    * Tail of DLL of ticket issue ops
233    */
234   struct TicketIssueOperation *issue_op_tail;
235
236   /**
237    * Head of DLL of ticket consume ops
238    */
239   struct ConsumeTicketOperation *consume_op_head;
240
241   /**
242    * Tail of DLL of ticket consume ops
243    */
244   struct ConsumeTicketOperation *consume_op_tail;
245
246   /**
247    * Head of DLL of attribute store ops
248    */
249   struct AttributeStoreHandle *store_op_head;
250
251   /**
252    * Tail of DLL of attribute store ops
253    */
254   struct AttributeStoreHandle *store_op_tail;
255
256 };
257
258 struct AttributeStoreHandle
259 {
260   /**
261    * DLL
262    */
263   struct AttributeStoreHandle *next;
264
265   /**
266    * DLL
267    */
268   struct AttributeStoreHandle *prev;
269
270   /**
271    * Client connection
272    */
273   struct IdpClient *client;
274
275   /**
276    * Identity
277    */
278   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
279
280   /**
281    * Identity pubkey
282    */
283   struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
284
285   /**
286    * QueueEntry
287    */
288   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
289
290   /**
291    * The attribute to store
292    */
293   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
294
295   /**
296    * The attribute expiration interval
297    */
298   struct GNUNET_TIME_Relative exp;
299
300   /**
301    * request id
302    */
303   uint32_t r_id;
304 };
305
306
307 struct ConsumeTicketOperation
308 {
309   /**
310    * DLL
311    */
312   struct ConsumeTicketOperation *next;
313
314   /**
315    * DLL
316    */
317   struct ConsumeTicketOperation *prev;
318
319   /**
320    * Client connection
321    */
322   struct IdpClient *client;
323
324   /**
325    * request id
326    */
327   uint32_t r_id;
328
329   /**
330    * Ticket consume handle
331    */
332   struct RECLAIM_TICKETS_ConsumeHandle *ch;
333 };
334
335
336 /**
337  * Updated attribute IDs
338  */
339 struct TicketAttributeUpdateEntry
340 {
341   /**
342    * DLL
343    */
344   struct TicketAttributeUpdateEntry *next;
345
346   /**
347    * DLL
348    */
349   struct TicketAttributeUpdateEntry *prev;
350
351   /**
352    * The old ID
353    */
354   uint64_t old_id;
355
356   /**
357    * The new ID
358    */
359   uint64_t new_id;
360 };
361
362 /**
363  * Ticket revocation request handle
364  */
365 struct TicketRevocationHandle
366 {
367   /**
368    * DLL
369    */
370   struct TicketRevocationHandle *prev;
371
372   /**
373    * DLL
374    */
375   struct TicketRevocationHandle *next;
376
377   /**
378    * Attribute updates
379    */
380   struct TicketAttributeUpdateEntry *attr_updates_head;
381
382   /**
383    * Attribute updates
384    */
385   struct TicketAttributeUpdateEntry *attr_updates_tail;
386
387   /**
388    * Client connection
389    */
390   struct IdpClient *client;
391
392   /**
393    * Attributes to reissue
394    */
395   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
396
397   /**
398    * Attributes to revoke
399    */
400   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *rvk_attrs;
401
402   /**
403    * Issuer Key
404    */
405   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
406
407   /**
408    * Ticket to issue
409    */
410   struct GNUNET_RECLAIM_Ticket ticket;
411
412   /**
413    * QueueEntry
414    */
415   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
416
417   /**
418    * Namestore iterator
419    */
420   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
421
422   /**
423    * Offset
424    */
425   uint32_t offset;
426
427   /**
428    * request id
429    */
430   uint32_t r_id;
431 };
432
433
434
435 /**
436  * Ticket issue operation handle
437  */
438 struct TicketIssueOperation
439 {
440   /**
441    * DLL
442    */
443   struct TicketIssueOperation *prev;
444
445   /**
446    * DLL
447    */
448   struct TicketIssueOperation *next;
449
450   /**
451    * Client connection
452    */
453   struct IdpClient *client;
454
455   /**
456    * request id
457    */
458   uint32_t r_id;
459 };
460
461
462 /**
463  * DLL for ego handles to egos containing the RECLAIM_ATTRS in a
464  * map in json_t format
465  *
466  */
467 struct EgoEntry
468 {
469   /**
470    * DLL
471    */
472   struct EgoEntry *next;
473
474   /**
475    * DLL
476    */
477   struct EgoEntry *prev;
478
479   /**
480    * Ego handle
481    */
482   struct GNUNET_IDENTITY_Ego *ego;
483
484   /**
485    * Attribute map. Contains the attributes as json_t
486    */
487   struct GNUNET_CONTAINER_MultiHashMap *attr_map;
488
489 };
490
491 /**
492  * Cleanup task
493  */
494 static void
495 cleanup()
496 {
497   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
498               "Cleaning up\n");
499
500   RECLAIM_TICKETS_deinit ();
501   GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
502                                               TKT_database));
503   GNUNET_free (db_lib_name);
504   db_lib_name = NULL;
505   if (NULL != timeout_task)
506     GNUNET_SCHEDULER_cancel (timeout_task);
507   if (NULL != update_task)
508     GNUNET_SCHEDULER_cancel (update_task);
509   if (NULL != identity_handle)
510     GNUNET_IDENTITY_disconnect (identity_handle);
511   if (NULL != nsh)
512     GNUNET_NAMESTORE_disconnect (nsh);
513 }
514
515 /**
516  * Shutdown task
517  *
518  * @param cls NULL
519  */
520 static void
521 do_shutdown (void *cls)
522 {
523   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
524               "Shutting down...\n");
525   cleanup();
526 }
527
528
529 static int
530 create_sym_key_from_ecdh (const struct GNUNET_HashCode *new_key_hash,
531                           struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
532                           struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
533 {
534   struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
535
536   GNUNET_CRYPTO_hash_to_enc (new_key_hash,
537                              &new_key_hash_str);
538   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
539   static const char ctx_key[] = "gnuid-aes-ctx-key";
540   GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
541                      new_key_hash, sizeof (struct GNUNET_HashCode),
542                      ctx_key, strlen (ctx_key),
543                      NULL, 0);
544   static const char ctx_iv[] = "gnuid-aes-ctx-iv";
545   GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
546                      new_key_hash, sizeof (struct GNUNET_HashCode),
547                      ctx_iv, strlen (ctx_iv),
548                      NULL, 0);
549   return GNUNET_OK;
550 }
551
552
553 static void
554 send_ticket_result (const struct IdpClient *client,
555                     uint32_t r_id,
556                     const struct GNUNET_RECLAIM_Ticket *ticket,
557                     uint32_t success)
558 {
559   struct TicketResultMessage *irm;
560   struct GNUNET_MQ_Envelope *env;
561   struct GNUNET_RECLAIM_Ticket *ticket_buf;
562
563   if (NULL != ticket)
564   {
565     env = GNUNET_MQ_msg_extra (irm,
566                                sizeof (struct GNUNET_RECLAIM_Ticket),
567                                GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
568     ticket_buf = (struct GNUNET_RECLAIM_Ticket *)&irm[1];
569     *ticket_buf = *ticket;
570   } else {
571     env = GNUNET_MQ_msg (irm,
572                          GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
573   }
574   //TODO add success member
575   irm->id = htonl (r_id);
576   GNUNET_MQ_send (client->mq,
577                   env);
578 }
579
580
581 static void
582 issue_ticket_result_cb (void *cls,
583                         struct GNUNET_RECLAIM_Ticket *ticket,
584                         uint32_t success,
585                         const char* emsg)
586 {
587   struct TicketIssueOperation *tio = cls;
588   if (GNUNET_OK != success)
589   {
590     send_ticket_result (tio->client,
591                         tio->r_id,
592                         NULL,
593                         GNUNET_SYSERR);
594     GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
595                                  tio->client->issue_op_tail,
596                                  tio);
597     GNUNET_free (tio);
598     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
599                 "Error issuing ticket: %s\n",
600                 emsg);
601     return;
602   }
603   send_ticket_result (tio->client,
604                       tio->r_id,
605                       ticket,
606                       GNUNET_SYSERR);
607   GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
608                                tio->client->issue_op_tail,
609                                tio);
610   GNUNET_free (tio);
611 }
612
613 static int
614 check_issue_ticket_message (void *cls,
615                             const struct IssueTicketMessage *im)
616 {
617   uint16_t size;
618
619   size = ntohs (im->header.size);
620   if (size <= sizeof (struct IssueTicketMessage))
621   {
622     GNUNET_break (0);
623     return GNUNET_SYSERR;
624   }
625   return GNUNET_OK;
626 }
627
628 static void
629 handle_issue_ticket_message (void *cls,
630                              const struct IssueTicketMessage *im)
631 {
632   struct TicketIssueOperation *tio;
633   struct IdpClient *idp = cls;
634   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
635   size_t attrs_len;
636
637   tio = GNUNET_new (struct TicketIssueOperation);
638   attrs_len = ntohs (im->attr_len);
639   attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char*)&im[1], attrs_len);
640   tio->r_id = ntohl (im->id);
641   tio->client = idp;
642   GNUNET_CONTAINER_DLL_insert (idp->issue_op_head,
643                                idp->issue_op_tail,
644                                tio);
645   RECLAIM_TICKETS_issue (&im->identity,
646                          attrs,
647                          &im->rp,
648                          &issue_ticket_result_cb,
649                          tio);
650   GNUNET_SERVICE_client_continue (idp->client);
651   GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
652 }
653
654 /**********************************************************
655  * Revocation
656  **********************************************************/
657
658 /**
659  * Cleanup revoke handle
660  *
661  * @param rh the ticket revocation handle
662  */
663 static void
664 cleanup_revoke_ticket_handle (struct TicketRevocationHandle *rh)
665 {
666   if (NULL != rh->attrs)
667     GNUNET_RECLAIM_ATTRIBUTE_list_destroy (rh->attrs);
668   if (NULL != rh->rvk_attrs)
669     GNUNET_RECLAIM_ATTRIBUTE_list_destroy (rh->rvk_attrs);
670   if (NULL != rh->ns_qe)
671     GNUNET_NAMESTORE_cancel (rh->ns_qe);
672   if (NULL != rh->ns_it)
673     GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
674   GNUNET_free (rh);
675 }
676
677 static int
678 serialize_authz_record (const struct GNUNET_RECLAIM_Ticket *ticket,
679                         const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
680                         struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
681                         char **result)
682 {
683   struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
684   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
685   struct GNUNET_CRYPTO_SymmetricSessionKey skey;
686   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
687   struct GNUNET_HashCode new_key_hash;
688   ssize_t enc_size;
689   char *enc_keyinfo;
690   char *buf;
691   char *write_ptr;
692   char attrs_str_len;
693   char* label;
694
695   GNUNET_assert (NULL != attrs->list_head);
696   attrs_str_len = 0;
697   for (le = attrs->list_head; NULL != le; le = le->next) {
698     attrs_str_len += 15 + 1; //TODO propery calculate
699   }
700   buf = GNUNET_malloc (attrs_str_len);
701   write_ptr = buf;
702   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
703               "Writing attributes\n");
704   for (le = attrs->list_head; NULL != le; le = le->next) {
705     label = GNUNET_STRINGS_data_to_string_alloc (&le->claim->id,
706                                                  sizeof (uint64_t));
707     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
708                 "Adding attribute to record: %s\n", label);
709
710     GNUNET_memcpy (write_ptr,
711                    label,
712                    strlen (label));
713     write_ptr[strlen (label)] = ',';
714     write_ptr += strlen (label) + 1;
715     GNUNET_free (label);
716   }
717   write_ptr--;
718   write_ptr[0] = '\0'; //replace last , with a 0-terminator
719   // ECDH keypair E = eG
720   *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
721   GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
722                                       &ecdh_pubkey);
723   enc_keyinfo = GNUNET_malloc (attrs_str_len);
724   // Derived key K = H(eB)
725   GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
726                                                         &ticket->audience,
727                                                         &new_key_hash));
728   create_sym_key_from_ecdh (&new_key_hash, &skey, &iv);
729   enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
730                                               attrs_str_len,
731                                               &skey, &iv,
732                                               enc_keyinfo);
733   *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
734                            enc_size);
735   GNUNET_memcpy (*result,
736                  &ecdh_pubkey,
737                  sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
738   GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
739                  enc_keyinfo,
740                  enc_size);
741   GNUNET_free (enc_keyinfo);
742   GNUNET_free (buf);
743   return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
744 }
745
746
747 /**
748  * Send revocation result
749  *
750  * @param rh ticket revocation handle
751  * @param success GNUNET_OK if successful result
752  */
753 static void
754 send_revocation_finished (struct TicketRevocationHandle *rh,
755                           uint32_t success)
756 {
757   struct GNUNET_MQ_Envelope *env;
758   struct RevokeTicketResultMessage *trm;
759
760   GNUNET_break(TKT_database->delete_ticket (TKT_database->cls,
761                                             &rh->ticket));
762
763   env = GNUNET_MQ_msg (trm,
764                        GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
765   trm->id = htonl (rh->r_id);
766   trm->success = htonl (success);
767   GNUNET_MQ_send (rh->client->mq,
768                   env);
769   GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head,
770                                rh->client->revoke_op_tail,
771                                rh);
772 }
773
774
775 /**
776  * Process ticket from database
777  *
778  * @param cls struct TicketIterationProcResult
779  * @param ticket the ticket
780  * @param attrs the attributes
781  */
782 static void
783 ticket_reissue_proc (void *cls,
784                      const struct GNUNET_RECLAIM_Ticket *ticket,
785                      const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs);
786
787 static void
788 revocation_reissue_tickets (struct TicketRevocationHandle *rh);
789
790
791 static void reissue_next (void *cls)
792 {
793   struct TicketRevocationHandle *rh = cls;
794   revocation_reissue_tickets (rh);
795 }
796
797
798 static void
799 reissue_ticket_cont (void *cls,
800                      int32_t success,
801                      const char *emsg)
802 {
803   struct TicketRevocationHandle *rh = cls;
804
805   rh->ns_qe = NULL;
806   if (GNUNET_SYSERR == success)
807   {
808     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
809                 "Unknown Error\n");
810     send_revocation_finished (rh, GNUNET_SYSERR);
811     cleanup_revoke_ticket_handle (rh);
812     return;
813   }
814   rh->offset++;
815   GNUNET_SCHEDULER_add_now (&reissue_next, rh);
816 }
817
818
819 /**
820  * Process ticket from database
821  *
822  * @param cls struct TicketIterationProcResult
823  * @param ticket the ticket
824  * @param attrs the attributes
825  */
826 static void
827 ticket_reissue_proc (void *cls,
828                      const struct GNUNET_RECLAIM_Ticket *ticket,
829                      const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
830 {
831   struct TicketRevocationHandle *rh = cls;
832   struct TicketAttributeUpdateEntry *tue;
833   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
834   struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
835   struct GNUNET_GNSRECORD_Data code_record[1];
836   int reissue_ticket;
837   size_t authz_record_len;
838   char *authz_record_data;
839   char *label;
840
841
842   if (NULL == ticket)
843   {
844     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
845                 "Iteration done\n");
846     return;
847   }
848
849   if (0 == memcmp (&ticket->audience,
850                    &rh->ticket.audience,
851                    sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
852   {
853     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
854                 "Do not reissue for this identity.!\n");
855     label = GNUNET_STRINGS_data_to_string_alloc (&rh->ticket.rnd,
856                                                  sizeof (uint64_t));
857     //Delete record
858     rh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
859                                                 &rh->identity,
860                                                 label,
861                                                 0,
862                                                 NULL,
863                                                 &reissue_ticket_cont,
864                                                 rh);
865
866     GNUNET_free (label);
867     return;
868   }
869
870   /*
871    * Check if any attribute of this ticket intersects with a rollover attribute
872    */
873   reissue_ticket = GNUNET_NO;
874   for (le = attrs->list_head; NULL != le; le = le->next)
875   {
876     for (tue = rh->attr_updates_head;
877          NULL != tue;
878          tue = tue->next)
879     {
880       if (tue->old_id == le->claim->id)
881       {
882         reissue_ticket = GNUNET_YES;
883         le->claim->id = tue->new_id;
884       }
885     }
886   }
887
888   if (GNUNET_NO == reissue_ticket)
889   {
890     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
891                 "Skipping ticket.\n");
892
893     rh->offset++;
894     GNUNET_SCHEDULER_add_now (&reissue_next, rh);
895     return;
896   }
897
898   //Create new ABE key for RP
899
900   /* If this is the RP we want to revoke attributes of, the do so */
901
902   //TODO rename function
903   authz_record_len = serialize_authz_record (ticket,
904                                              attrs,
905                                              &ecdhe_privkey,
906                                              &authz_record_data);
907   code_record[0].data = authz_record_data;
908   code_record[0].data_size = authz_record_len;
909   code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
910   code_record[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_AUTHZ;
911   code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
912
913   label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
914                                                sizeof (uint64_t));
915   //Publish record
916   rh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
917                                               &rh->identity,
918                                               label,
919                                               1,
920                                               code_record,
921                                               &reissue_ticket_cont,
922                                               rh);
923   GNUNET_free (ecdhe_privkey);
924   GNUNET_free (label);
925   GNUNET_free (authz_record_data);
926 }
927
928
929 /* Prototype for below function */
930 static void
931 attr_reenc_cont (void *cls,
932                  int32_t success,
933                  const char *emsg);
934
935 static void
936 revocation_reissue_tickets (struct TicketRevocationHandle *rh)
937 {
938   int ret;
939   /* Done, issue new keys */
940   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
941               "Revocation Phase III: Reissuing Tickets\n");
942   if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
943                                                              &rh->ticket.identity,
944                                                              GNUNET_NO,
945                                                              rh->offset,
946                                                              &ticket_reissue_proc,
947                                                              rh)))
948   {
949     GNUNET_break (0);
950   }
951   if (GNUNET_NO == ret)
952   {
953     send_revocation_finished (rh, GNUNET_OK);
954     cleanup_revoke_ticket_handle (rh);
955     return;
956   }
957 }
958
959 /**
960  * Failed to check for attribute
961  */
962 static void
963 check_attr_error (void *cls)
964 {
965   struct TicketRevocationHandle *rh = cls;
966   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
967               "Unable to check for existing attribute\n");
968   rh->ns_qe = NULL;
969   send_revocation_finished (rh, GNUNET_SYSERR);
970   cleanup_revoke_ticket_handle (rh);
971 }
972
973
974 /**
975  * Revoke next attribte by reencryption with
976  * new ABE master
977  */
978 static void
979 reenc_next_attribute (void *cls);
980
981 /**
982  * Check for existing attribute and overwrite
983  */
984 static void
985 check_attr_cb (void *cls,
986                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
987                const char *label,
988                unsigned int rd_count,
989                const struct GNUNET_GNSRECORD_Data *rd_old)
990 {
991   struct TicketRevocationHandle *rh = cls;
992   struct TicketAttributeUpdateEntry *tue;
993   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
994   struct GNUNET_GNSRECORD_Data rd[1];
995   char* buf;
996   size_t buf_size;
997   char* new_label;
998
999   rh->ns_qe = NULL;
1000   if (1 != rd_count) {
1001     le = rh->attrs->list_head;
1002     GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1003                                  rh->attrs->list_tail,
1004                                  le);
1005     GNUNET_assert (NULL != rh->rvk_attrs);
1006     GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
1007                                  rh->rvk_attrs->list_tail,
1008                                  le);
1009     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1010                 "Re-encrypting next attribute\n");
1011     GNUNET_SCHEDULER_add_now (&reenc_next_attribute,
1012                               rh);
1013     return;
1014   }
1015
1016   buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim);
1017   buf = GNUNET_malloc (buf_size);
1018   rh->attrs->list_head->claim->version++;
1019   GNUNET_RECLAIM_ATTRIBUTE_serialize (rh->attrs->list_head->claim,
1020                                       buf);
1021   tue = GNUNET_new (struct TicketAttributeUpdateEntry);
1022   tue->old_id = rh->attrs->list_head->claim->id;
1023   tue->new_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1024                                           UINT64_MAX);
1025   GNUNET_CONTAINER_DLL_insert (rh->attr_updates_head,
1026                                rh->attr_updates_tail,
1027                                tue);
1028   rh->attrs->list_head->claim->id = tue->new_id;
1029   new_label = GNUNET_STRINGS_data_to_string_alloc (&tue->new_id,
1030                                                    sizeof (uint64_t));
1031   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1032               "New attr id %s\n", new_label);
1033   rd[0].data_size = buf_size;
1034   rd[0].data = buf;
1035   rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR;
1036   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1037   rd[0].expiration_time = rd_old[0].expiration_time;
1038   rh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1039                                               &rh->identity,
1040                                               new_label,
1041                                               1,
1042                                               rd,
1043                                               &attr_reenc_cont,
1044                                               rh);
1045 }
1046
1047
1048 /**
1049  * Revoke next attribte by reencryption with
1050  * new ABE master
1051  */
1052 static void
1053 reenc_next_attribute (void *cls)
1054 {
1055   struct TicketRevocationHandle *rh = cls;
1056   char *label;
1057   if (NULL == rh->attrs->list_head)
1058   {
1059     revocation_reissue_tickets (rh);
1060     return;
1061   }
1062   /* First check if attribute still exists */
1063   label = GNUNET_STRINGS_data_to_string_alloc (&rh->attrs->list_head->claim->id,
1064                                                sizeof (uint64_t));
1065   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ID: %lu\n", rh->attrs->list_head->claim->id);
1066   rh->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
1067                                                &rh->identity,
1068                                                label,
1069                                                &check_attr_error,
1070                                                rh,
1071                                                &check_attr_cb,
1072                                                rh);
1073   GNUNET_free (label);
1074 }
1075
1076
1077 /**
1078  * Namestore callback after revoked attribute
1079  * is stored
1080  */
1081 static void
1082 attr_reenc_cont (void *cls,
1083                  int32_t success,
1084                  const char *emsg)
1085 {
1086   struct TicketRevocationHandle *rh = cls;
1087   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
1088
1089   rh->ns_qe = NULL;
1090   if (GNUNET_SYSERR == success)
1091   {
1092     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1093                 "Failed to reencrypt attribute %s\n",
1094                 emsg);
1095     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1096     return;
1097   }
1098   if (NULL == rh->attrs->list_head)
1099   {
1100     revocation_reissue_tickets (rh);
1101     return;
1102   }
1103   le = rh->attrs->list_head;
1104   GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1105                                rh->attrs->list_tail,
1106                                le);
1107   GNUNET_assert (NULL != rh->rvk_attrs);
1108   GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
1109                                rh->rvk_attrs->list_tail,
1110                                le);
1111
1112
1113   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1114               "Re-encrypting next attribute\n");
1115   reenc_next_attribute (rh);
1116 }
1117
1118
1119 static void
1120 process_attributes_to_update (void *cls,
1121                               const struct GNUNET_RECLAIM_Ticket *ticket,
1122                               const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
1123 {
1124   struct TicketRevocationHandle *rh = cls;
1125
1126   rh->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (attrs);
1127   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1128               "Revocation Phase I: Collecting attributes\n");
1129   /* Reencrypt all attributes with new key */
1130   if (NULL == rh->attrs->list_head)
1131   {
1132     /* No attributes to reencrypt */
1133     send_revocation_finished (rh, GNUNET_OK);
1134     cleanup_revoke_ticket_handle (rh);
1135     return;
1136   } else {
1137     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1138                 "Revocation Phase II: Re-encrypting attributes\n");
1139     reenc_next_attribute (rh);
1140   }
1141
1142 }
1143
1144
1145 static int
1146 check_revoke_ticket_message(void *cls,
1147                             const struct RevokeTicketMessage *im)
1148 {
1149   uint16_t size;
1150
1151   size = ntohs (im->header.size);
1152   if (size <= sizeof (struct RevokeTicketMessage))
1153   {
1154     GNUNET_break (0);
1155     return GNUNET_SYSERR;
1156   }
1157   return GNUNET_OK;
1158 }
1159
1160 static void
1161 handle_revoke_ticket_message (void *cls,
1162                               const struct RevokeTicketMessage *rm)
1163 {
1164   struct TicketRevocationHandle *rh;
1165   struct IdpClient *idp = cls;
1166   struct GNUNET_RECLAIM_Ticket *ticket;
1167
1168   rh = GNUNET_new (struct TicketRevocationHandle);
1169   ticket = (struct GNUNET_RECLAIM_Ticket*)&rm[1];
1170   rh->rvk_attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
1171   rh->ticket = *ticket;
1172   rh->r_id = ntohl (rm->id);
1173   rh->client = idp;
1174   rh->identity = rm->identity;
1175   GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
1176                                       &rh->ticket.identity);
1177   GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head,
1178                                idp->revoke_op_tail,
1179                                rh);
1180   /**
1181    * TODO replace with GNS storage
1182    */
1183   TKT_database->get_ticket_attributes (TKT_database->cls,
1184                                        &rh->ticket,
1185                                        &process_attributes_to_update,
1186                                        rh);
1187   GNUNET_SERVICE_client_continue (idp->client);
1188
1189 }
1190
1191 static int
1192 check_consume_ticket_message (void *cls,
1193                               const struct ConsumeTicketMessage *cm)
1194 {
1195   uint16_t size;
1196
1197   size = ntohs (cm->header.size);
1198   if (size <= sizeof (struct ConsumeTicketMessage))
1199   {
1200     GNUNET_break (0);
1201     return GNUNET_SYSERR;
1202   }
1203   return GNUNET_OK;
1204 }
1205
1206 static void
1207 consume_result_cb (void *cls,
1208                    const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1209                    const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
1210                    uint32_t success,
1211                    const char *emsg)
1212 {
1213   struct ConsumeTicketOperation *cop = cls;
1214   struct ConsumeTicketResultMessage *crm;
1215   struct GNUNET_MQ_Envelope *env;
1216   char *data_tmp;
1217   size_t attrs_len;
1218   if (GNUNET_OK != success)
1219   {
1220     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1221                 "Error consuming ticket: %s\n",
1222                 emsg);
1223   }
1224   attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
1225   env = GNUNET_MQ_msg_extra (crm,
1226                              attrs_len,
1227                              GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
1228   crm->id = htonl (cop->r_id);
1229   crm->attrs_len = htons (attrs_len);
1230   crm->identity = *identity;
1231   crm->result = htonl (success);
1232   data_tmp = (char *) &crm[1];
1233   GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs,
1234                                            data_tmp);
1235   GNUNET_MQ_send (cop->client->mq, env);
1236   GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
1237                                cop->client->consume_op_tail,
1238                                cop);
1239   GNUNET_free (cop);
1240
1241 }
1242
1243 static void
1244 handle_consume_ticket_message (void *cls,
1245                                const struct ConsumeTicketMessage *cm)
1246 {
1247   struct ConsumeTicketOperation *cop;
1248   struct GNUNET_RECLAIM_Ticket *ticket;
1249   struct IdpClient *idp = cls;
1250
1251   cop = GNUNET_new (struct ConsumeTicketOperation);
1252   cop->r_id = ntohl (cm->id);
1253   cop->client = idp;
1254   ticket = (struct GNUNET_RECLAIM_Ticket*)&cm[1];
1255   cop->ch = RECLAIM_TICKETS_consume (&cm->identity,
1256                                      ticket,
1257                                      &consume_result_cb,
1258                                      cop);
1259   GNUNET_CONTAINER_DLL_insert (idp->consume_op_head,
1260                                idp->consume_op_tail,
1261                                cop);
1262   GNUNET_SERVICE_client_continue (idp->client);
1263 }
1264
1265 /*****************************************
1266  * Attribute store
1267  *****************************************/
1268
1269 /**
1270  * Cleanup attribute store handle
1271  *
1272  * @param handle handle to clean up
1273  */
1274 static void
1275 cleanup_as_handle (struct AttributeStoreHandle *ash)
1276 {
1277   if (NULL != ash->ns_qe)
1278     GNUNET_NAMESTORE_cancel (ash->ns_qe);
1279   if (NULL != ash->claim)
1280     GNUNET_free (ash->claim);
1281   GNUNET_free (ash);
1282 }
1283
1284 static void
1285 attr_store_cont (void *cls,
1286                  int32_t success,
1287                  const char *emsg)
1288 {
1289   struct AttributeStoreHandle *ash = cls;
1290   struct GNUNET_MQ_Envelope *env;
1291   struct AttributeStoreResultMessage *acr_msg;
1292
1293   ash->ns_qe = NULL;
1294   GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1295                                ash->client->store_op_tail,
1296                                ash);
1297
1298   if (GNUNET_SYSERR == success)
1299   {
1300     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1301                 "Failed to store attribute %s\n",
1302                 emsg);
1303     cleanup_as_handle (ash);
1304     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1305     return;
1306   }
1307
1308   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1309               "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1310   env = GNUNET_MQ_msg (acr_msg,
1311                        GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE_RESPONSE);
1312   acr_msg->id = htonl (ash->r_id);
1313   acr_msg->op_result = htonl (GNUNET_OK);
1314   GNUNET_MQ_send (ash->client->mq,
1315                   env);
1316   cleanup_as_handle (ash);
1317 }
1318
1319 /**
1320  * Adds a new attribute
1321  *
1322  * @param cls the AttributeStoreHandle
1323  */
1324 static void
1325 attr_store_task (void *cls)
1326 {
1327   struct AttributeStoreHandle *ash = cls;
1328   struct GNUNET_GNSRECORD_Data rd[1];
1329   char* buf;
1330   char* label;
1331   size_t buf_size;
1332
1333   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1334               "Storing attribute\n");
1335   buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (ash->claim);
1336   buf = GNUNET_malloc (buf_size);
1337   //Give the ash a new id
1338   ash->claim->id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1339                                              UINT64_MAX);
1340   GNUNET_RECLAIM_ATTRIBUTE_serialize (ash->claim,
1341                                       buf);
1342   label = GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id,
1343                                                sizeof (uint64_t));
1344   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1345               "Encrypting with label %s\n", label);
1346
1347   rd[0].data_size = buf_size;
1348   rd[0].data = buf;
1349   rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR;
1350   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1351   rd[0].expiration_time = ash->exp.rel_value_us;
1352   ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1353                                                &ash->identity,
1354                                                label,
1355                                                1,
1356                                                rd,
1357                                                &attr_store_cont,
1358                                                ash);
1359   GNUNET_free (buf);
1360 }
1361
1362
1363 static int
1364 check_attribute_store_message(void *cls,
1365                               const struct AttributeStoreMessage *sam)
1366 {
1367   uint16_t size;
1368
1369   size = ntohs (sam->header.size);
1370   if (size <= sizeof (struct AttributeStoreMessage))
1371   {
1372     GNUNET_break (0);
1373     return GNUNET_SYSERR;
1374   }
1375   return GNUNET_OK;
1376 }
1377
1378
1379 static void
1380 handle_attribute_store_message (void *cls,
1381                                 const struct AttributeStoreMessage *sam)
1382 {
1383   struct AttributeStoreHandle *ash;
1384   struct IdpClient *idp = cls;
1385   size_t data_len;
1386   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1387               "Received ATTRIBUTE_STORE message\n");
1388
1389   data_len = ntohs (sam->attr_len);
1390
1391   ash = GNUNET_new (struct AttributeStoreHandle);
1392   ash->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char*)&sam[1],
1393                                                      data_len);
1394
1395   ash->r_id = ntohl (sam->id);
1396   ash->identity = sam->identity;
1397   ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1398   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1399                                       &ash->identity_pkey);
1400
1401   GNUNET_SERVICE_client_continue (idp->client);
1402   ash->client = idp;
1403   GNUNET_CONTAINER_DLL_insert (idp->store_op_head,
1404                                idp->store_op_tail,
1405                                ash);
1406   GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1407 }
1408
1409 /*************************************************
1410  * Attrubute iteration
1411  *************************************************/
1412
1413 static void
1414 cleanup_attribute_iter_handle (struct AttributeIterator *ai)
1415 {
1416   GNUNET_free (ai);
1417 }
1418
1419 static void
1420 attr_iter_error (void *cls)
1421 {
1422   struct AttributeIterator *ai = cls;
1423   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1424               "Failed to iterate over attributes\n");
1425   GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1426                                ai->client->attr_iter_tail,
1427                                ai);
1428   cleanup_attribute_iter_handle (ai);
1429   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1430 }
1431
1432 static void
1433 attr_iter_finished (void *cls)
1434 {
1435   struct AttributeIterator *ai = cls;
1436   struct GNUNET_MQ_Envelope *env;
1437   struct AttributeResultMessage *arm;
1438
1439   env = GNUNET_MQ_msg (arm,
1440                        GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1441   arm->id = htonl (ai->request_id);
1442   arm->attr_len = htons (0);
1443   GNUNET_MQ_send (ai->client->mq, env);
1444   GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1445                                ai->client->attr_iter_tail,
1446                                ai);
1447   cleanup_attribute_iter_handle (ai);
1448 }
1449
1450 static void
1451 attr_iter_cb (void *cls,
1452               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1453               const char *label,
1454               unsigned int rd_count,
1455               const struct GNUNET_GNSRECORD_Data *rd)
1456 {
1457   struct AttributeIterator *ai = cls;
1458   struct AttributeResultMessage *arm;
1459   struct GNUNET_MQ_Envelope *env;
1460   char* data_tmp;
1461
1462   if (rd_count != 1)
1463   {
1464     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
1465                                          1);
1466     return;
1467   }
1468
1469   if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd->record_type)
1470   {
1471     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
1472                                          1);
1473     return;
1474   }
1475   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1476               "Found attribute under: %s\n", label);
1477   env = GNUNET_MQ_msg_extra (arm,
1478                              rd->data_size,
1479                              GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1480   arm->id = htonl (ai->request_id);
1481   arm->attr_len = htons (rd->data_size);
1482   GNUNET_CRYPTO_ecdsa_key_get_public (zone,
1483                                       &arm->identity);
1484   data_tmp = (char *) &arm[1];
1485   GNUNET_memcpy (data_tmp,
1486                  rd->data,
1487                  rd->data_size);
1488   GNUNET_MQ_send (ai->client->mq, env);
1489 }
1490
1491
1492 static void
1493 handle_iteration_start (void *cls,
1494                         const struct AttributeIterationStartMessage *ais_msg)
1495 {
1496   struct IdpClient *idp = cls;
1497   struct AttributeIterator *ai;
1498
1499   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1500               "Received ATTRIBUTE_ITERATION_START message\n");
1501   ai = GNUNET_new (struct AttributeIterator);
1502   ai->request_id = ntohl (ais_msg->id);
1503   ai->client = idp;
1504   ai->identity = ais_msg->identity;
1505
1506   GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head,
1507                                idp->attr_iter_tail,
1508                                ai);
1509   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1510                                                      &ai->identity,
1511                                                      &attr_iter_error,
1512                                                      ai,
1513                                                      &attr_iter_cb,
1514                                                      ai,
1515                                                      &attr_iter_finished,
1516                                                      ai);
1517   GNUNET_SERVICE_client_continue (idp->client);
1518 }
1519
1520
1521 static void
1522 handle_iteration_stop (void *cls,
1523                        const struct AttributeIterationStopMessage *ais_msg)
1524 {
1525   struct IdpClient *idp = cls;
1526   struct AttributeIterator *ai;
1527   uint32_t rid;
1528
1529   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1530               "Received `%s' message\n",
1531               "ATTRIBUTE_ITERATION_STOP");
1532   rid = ntohl (ais_msg->id);
1533   for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1534     if (ai->request_id == rid)
1535       break;
1536   if (NULL == ai)
1537   {
1538     GNUNET_break (0);
1539     GNUNET_SERVICE_client_drop (idp->client);
1540     return;
1541   }
1542   GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head,
1543                                idp->attr_iter_tail,
1544                                ai);
1545   GNUNET_free (ai);
1546   GNUNET_SERVICE_client_continue (idp->client);
1547 }
1548
1549
1550 static void
1551 handle_iteration_next (void *cls,
1552                        const struct AttributeIterationNextMessage *ais_msg)
1553 {
1554   struct IdpClient *idp = cls;
1555   struct AttributeIterator *ai;
1556   uint32_t rid;
1557
1558   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1559               "Received ATTRIBUTE_ITERATION_NEXT message\n");
1560   rid = ntohl (ais_msg->id);
1561   for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1562     if (ai->request_id == rid)
1563       break;
1564   if (NULL == ai)
1565   {
1566     GNUNET_break (0);
1567     GNUNET_SERVICE_client_drop (idp->client);
1568     return;
1569   }
1570   GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
1571                                        1);
1572   GNUNET_SERVICE_client_continue (idp->client);
1573 }
1574
1575 /******************************************************
1576  * Ticket iteration
1577  ******************************************************/
1578
1579 static void
1580 ticket_iter_cb (void *cls,
1581                 struct GNUNET_RECLAIM_Ticket *ticket)
1582 {
1583   struct TicketIteration *ti = cls;
1584   struct GNUNET_MQ_Envelope *env;
1585   struct TicketResultMessage *trm;
1586
1587   if (NULL == ticket)
1588   {
1589     /* send empty response to indicate end of list */
1590     env = GNUNET_MQ_msg (trm,
1591                          GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1592     GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
1593                                  ti->client->ticket_iter_tail,
1594                                  ti);
1595   } else {
1596     env = GNUNET_MQ_msg_extra (trm,
1597                                sizeof (struct GNUNET_RECLAIM_Ticket),
1598                                GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1599   }
1600   trm->id = htonl (ti->r_id);
1601   GNUNET_MQ_send (ti->client->mq,
1602                   env);
1603   if (NULL == ticket)
1604     GNUNET_free (ti);
1605 }
1606
1607 static void
1608 handle_ticket_iteration_start (void *cls,
1609                                const struct TicketIterationStartMessage *tis_msg)
1610 {
1611   struct IdpClient *client = cls;
1612   struct TicketIteration *ti;
1613
1614   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1615               "Received TICKET_ITERATION_START message\n");
1616   ti = GNUNET_new (struct TicketIteration);
1617   ti->r_id = ntohl (tis_msg->id);
1618   ti->client = client;
1619
1620   GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
1621                                client->ticket_iter_tail,
1622                                ti);
1623   ti->iter = RECLAIM_TICKETS_iteration_start (&tis_msg->identity,
1624                                               &ticket_iter_cb,
1625                                               ti);
1626   GNUNET_SERVICE_client_continue (client->client);
1627 }
1628
1629
1630 static void
1631 handle_ticket_iteration_stop (void *cls,
1632                               const struct TicketIterationStopMessage *tis_msg)
1633 {
1634   struct IdpClient *client = cls;
1635   struct TicketIteration *ti;
1636   uint32_t rid;
1637
1638   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1639               "Received `%s' message\n",
1640               "TICKET_ITERATION_STOP");
1641   rid = ntohl (tis_msg->id);
1642   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1643     if (ti->r_id == rid)
1644       break;
1645   if (NULL == ti)
1646   {
1647     GNUNET_break (0);
1648     GNUNET_SERVICE_client_drop (client->client);
1649     return;
1650   }
1651   RECLAIM_TICKETS_iteration_stop (ti->iter);
1652   GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
1653                                client->ticket_iter_tail,
1654                                ti);
1655   GNUNET_free (ti);
1656   GNUNET_SERVICE_client_continue (client->client);
1657 }
1658
1659
1660 static void
1661 handle_ticket_iteration_next (void *cls,
1662                               const struct TicketIterationNextMessage *tis_msg)
1663 {
1664   struct IdpClient *client = cls;
1665   struct TicketIteration *ti;
1666   uint32_t rid;
1667
1668   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1669               "Received TICKET_ITERATION_NEXT message\n");
1670   rid = ntohl (tis_msg->id);
1671   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1672     if (ti->r_id == rid)
1673       break;
1674   if (NULL == ti)
1675   {
1676     GNUNET_break (0);
1677     GNUNET_SERVICE_client_drop (client->client);
1678     return;
1679   }
1680   RECLAIM_TICKETS_iteration_next (ti->iter);
1681   GNUNET_SERVICE_client_continue (client->client);
1682 }
1683
1684
1685
1686
1687 /**
1688  * Main function that will be run
1689  *
1690  * @param cls closure
1691  * @param c the configuration used
1692  * @param server the service handle
1693  */
1694 static void
1695 run (void *cls,
1696      const struct GNUNET_CONFIGURATION_Handle *c,
1697      struct GNUNET_SERVICE_Handle *server)
1698 {
1699   char *database;
1700   cfg = c;
1701
1702
1703   if (GNUNET_OK != RECLAIM_TICKETS_init (cfg))
1704   {
1705     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1706                 "Unable to initialized TICKETS subsystem.\n");
1707     GNUNET_SCHEDULER_shutdown ();
1708     return;
1709   }
1710   //Connect to identity and namestore services
1711   nsh = GNUNET_NAMESTORE_connect (cfg);
1712   if (NULL == nsh)
1713   {
1714     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
1715   }
1716
1717   identity_handle = GNUNET_IDENTITY_connect (cfg,
1718                                              NULL,
1719                                              NULL);
1720   /* Loading DB plugin */
1721   if (GNUNET_OK !=
1722       GNUNET_CONFIGURATION_get_value_string (cfg,
1723                                              "reclaim",
1724                                              "database",
1725                                              &database))
1726     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1727                 "No database backend configured\n");
1728   GNUNET_asprintf (&db_lib_name,
1729                    "libgnunet_plugin_reclaim_%s",
1730                    database);
1731   TKT_database = GNUNET_PLUGIN_load (db_lib_name,
1732                                      (void *) cfg);
1733   GNUNET_free (database);
1734   if (NULL == TKT_database)
1735   {
1736     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1737                 "Could not load database backend `%s'\n",
1738                 db_lib_name);
1739     GNUNET_SCHEDULER_shutdown ();
1740     return;
1741   }
1742
1743   if (GNUNET_OK ==
1744       GNUNET_CONFIGURATION_get_value_time (cfg,
1745                                            "reclaim",
1746                                            "TOKEN_EXPIRATION_INTERVAL",
1747                                            &token_expiration_interval))
1748   {
1749     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1750                 "Time window for zone iteration: %s\n",
1751                 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
1752                                                         GNUNET_YES));
1753   } else {
1754     token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
1755   }
1756
1757   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1758 }
1759
1760 /**
1761  * Called whenever a client is disconnected.
1762  *
1763  * @param cls closure
1764  * @param client identification of the client
1765  * @param app_ctx @a client
1766  */
1767 static void
1768 client_disconnect_cb (void *cls,
1769                       struct GNUNET_SERVICE_Client *client,
1770                       void *app_ctx)
1771 {
1772   struct IdpClient *idp = app_ctx;
1773   struct AttributeIterator *ai;
1774   struct TicketIteration *ti;
1775   struct TicketRevocationHandle *rh;
1776   struct TicketIssueOperation *iss;
1777   struct ConsumeTicketOperation *ct;
1778   struct AttributeStoreHandle *as;
1779
1780   //TODO other operations
1781
1782   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1783               "Client %p disconnected\n",
1784               client);
1785
1786   while (NULL != (iss = idp->issue_op_head))
1787   {
1788     GNUNET_CONTAINER_DLL_remove (idp->issue_op_head,
1789                                  idp->issue_op_tail,
1790                                  iss);
1791     GNUNET_free (iss);
1792   }
1793   while (NULL != (ct = idp->consume_op_head))
1794   {
1795     GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
1796                                  idp->consume_op_tail,
1797                                  ct);
1798     if (NULL != ct->ch)
1799       RECLAIM_TICKETS_consume_cancel (ct->ch);
1800     GNUNET_free (ct);
1801   }
1802   while (NULL != (as = idp->store_op_head))
1803   {
1804     GNUNET_CONTAINER_DLL_remove (idp->store_op_head,
1805                                  idp->store_op_tail,
1806                                  as);
1807     cleanup_as_handle (as);
1808   }
1809
1810   while (NULL != (ai = idp->attr_iter_head))
1811   {
1812     GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head,
1813                                  idp->attr_iter_tail,
1814                                  ai);
1815     cleanup_attribute_iter_handle (ai);
1816   }
1817   while (NULL != (rh = idp->revoke_op_head))
1818   {
1819     GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head,
1820                                  idp->revoke_op_tail,
1821                                  rh);
1822     cleanup_revoke_ticket_handle (rh);
1823   }
1824   while (NULL != (ti = idp->ticket_iter_head))
1825   {
1826     GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
1827                                  idp->ticket_iter_tail,
1828                                  ti);
1829     GNUNET_free (ti);
1830   }
1831   GNUNET_free (idp);
1832 }
1833
1834
1835 /**
1836  * Add a client to our list of active clients.
1837  *
1838  * @param cls NULL
1839  * @param client client to add
1840  * @param mq message queue for @a client
1841  * @return internal namestore client structure for this client
1842  */
1843 static void *
1844 client_connect_cb (void *cls,
1845                    struct GNUNET_SERVICE_Client *client,
1846                    struct GNUNET_MQ_Handle *mq)
1847 {
1848   struct IdpClient *idp;
1849   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1850               "Client %p connected\n",
1851               client);
1852   idp = GNUNET_new (struct IdpClient);
1853   idp->client = client;
1854   idp->mq = mq;
1855   return idp;
1856 }
1857
1858
1859
1860 /**
1861  * Define "main" method using service macro.
1862  */
1863 GNUNET_SERVICE_MAIN
1864 ("reclaim",
1865  GNUNET_SERVICE_OPTION_NONE,
1866  &run,
1867  &client_connect_cb,
1868  &client_disconnect_cb,
1869  NULL,
1870  GNUNET_MQ_hd_var_size (attribute_store_message,
1871                         GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
1872                         struct AttributeStoreMessage,
1873                         NULL),
1874  GNUNET_MQ_hd_fixed_size (iteration_start,
1875                           GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
1876                           struct AttributeIterationStartMessage,
1877                           NULL),
1878  GNUNET_MQ_hd_fixed_size (iteration_next,
1879                           GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
1880                           struct AttributeIterationNextMessage,
1881                           NULL),
1882  GNUNET_MQ_hd_fixed_size (iteration_stop,
1883                           GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
1884                           struct AttributeIterationStopMessage,
1885                           NULL),
1886  GNUNET_MQ_hd_var_size (issue_ticket_message,
1887                         GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
1888                         struct IssueTicketMessage,
1889                         NULL),
1890  GNUNET_MQ_hd_var_size (consume_ticket_message,
1891                         GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
1892                         struct ConsumeTicketMessage,
1893                         NULL),
1894  GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1895                           GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
1896                           struct TicketIterationStartMessage,
1897                           NULL),
1898  GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
1899                           GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
1900                           struct TicketIterationNextMessage,
1901                           NULL),
1902  GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
1903                           GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
1904                           struct TicketIterationStopMessage,
1905                           NULL),
1906  GNUNET_MQ_hd_var_size (revoke_ticket_message,
1907                         GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
1908                         struct RevokeTicketMessage,
1909                         NULL),
1910  GNUNET_MQ_handler_end());
1911 /* end of gnunet-service-reclaim.c */