use NULL value in load_path_suffix to NOT load any files
[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-service-reclaim_tickets.h"
29 #include "gnunet_constants.h"
30 #include "gnunet_gnsrecord_lib.h"
31 #include "gnunet_protocols.h"
32 #include "gnunet_reclaim_attribute_lib.h"
33 #include "gnunet_reclaim_service.h"
34 #include "gnunet_signatures.h"
35 #include "reclaim.h"
36
37
38 /**
39  * Namestore handle
40  */
41 static struct GNUNET_NAMESTORE_Handle *nsh;
42
43 /**
44  * Timeout task
45  */
46 static struct GNUNET_SCHEDULER_Task *timeout_task;
47
48 /**
49  * Our configuration.
50  */
51 static const struct GNUNET_CONFIGURATION_Handle *cfg;
52
53 /**
54  * An idp client
55  */
56 struct IdpClient;
57
58 /**
59  * A ticket iteration operation.
60  */
61 struct TicketIteration
62 {
63   /**
64    * DLL
65    */
66   struct TicketIteration *next;
67
68   /**
69    * DLL
70    */
71   struct TicketIteration *prev;
72
73   /**
74    * Client which intiated this zone iteration
75    */
76   struct IdpClient *client;
77
78   /**
79    * The operation id fot the iteration in the response for the client
80    */
81   uint32_t r_id;
82
83   /**
84    * The ticket iterator
85    */
86   struct RECLAIM_TICKETS_Iterator *iter;
87 };
88
89
90 /**
91  * An attribute iteration operation.
92  */
93 struct AttributeIterator
94 {
95   /**
96    * Next element in the DLL
97    */
98   struct AttributeIterator *next;
99
100   /**
101    * Previous element in the DLL
102    */
103   struct AttributeIterator *prev;
104
105   /**
106    * IDP client which intiated this zone iteration
107    */
108   struct IdpClient *client;
109
110   /**
111    * Key of the zone we are iterating over.
112    */
113   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
114
115   /**
116    * Namestore iterator
117    */
118   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
119
120   /**
121    * The operation id fot the zone iteration in the response for the client
122    */
123   uint32_t request_id;
124 };
125
126
127 /**
128  * An idp client
129  */
130 struct IdpClient
131 {
132   /**
133    * DLL
134    */
135   struct IdpClient *prev;
136
137   /**
138    * DLL
139    */
140   struct IdpClient *next;
141
142   /**
143    * The client
144    */
145   struct GNUNET_SERVICE_Client *client;
146
147   /**
148    * Message queue for transmission to @e client
149    */
150   struct GNUNET_MQ_Handle *mq;
151
152   /**
153    * Head of the DLL of
154    * Attribute iteration operations in
155    * progress initiated by this client
156    */
157   struct AttributeIterator *attr_iter_head;
158
159   /**
160    * Tail of the DLL of
161    * Attribute iteration operations
162    * in progress initiated by this client
163    */
164   struct AttributeIterator *attr_iter_tail;
165
166   /**
167    * Head of DLL of ticket iteration ops
168    */
169   struct TicketIteration *ticket_iter_head;
170
171   /**
172    * Tail of DLL of ticket iteration ops
173    */
174   struct TicketIteration *ticket_iter_tail;
175
176   /**
177    * Head of DLL of ticket revocation ops
178    */
179   struct TicketRevocationOperation *revoke_op_head;
180
181   /**
182    * Tail of DLL of ticket revocation ops
183    */
184   struct TicketRevocationOperation *revoke_op_tail;
185
186   /**
187    * Head of DLL of ticket issue ops
188    */
189   struct TicketIssueOperation *issue_op_head;
190
191   /**
192    * Tail of DLL of ticket issue ops
193    */
194   struct TicketIssueOperation *issue_op_tail;
195
196   /**
197    * Head of DLL of ticket consume ops
198    */
199   struct ConsumeTicketOperation *consume_op_head;
200
201   /**
202    * Tail of DLL of ticket consume ops
203    */
204   struct ConsumeTicketOperation *consume_op_tail;
205
206   /**
207    * Head of DLL of attribute store ops
208    */
209   struct AttributeStoreHandle *store_op_head;
210
211   /**
212    * Tail of DLL of attribute store ops
213    */
214   struct AttributeStoreHandle *store_op_tail;
215   /**
216    * Head of DLL of attribute delete ops
217    */
218   struct AttributeDeleteHandle *delete_op_head;
219
220   /**
221    * Tail of DLL of attribute delete ops
222    */
223   struct AttributeDeleteHandle *delete_op_tail;
224 };
225
226
227 /**
228  * Handle for attribute deletion request
229  */
230 struct AttributeDeleteHandle
231 {
232   /**
233    * DLL
234    */
235   struct AttributeDeleteHandle *next;
236
237   /**
238    * DLL
239    */
240   struct AttributeDeleteHandle *prev;
241
242   /**
243    * Client connection
244    */
245   struct IdpClient *client;
246
247   /**
248    * Identity
249    */
250   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
251
252
253   /**
254    * QueueEntry
255    */
256   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
257
258   /**
259    * Iterator
260    */
261   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
262
263   /**
264    * The attribute to delete
265    */
266   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
267
268   /**
269    * The attestation to delete
270    */
271   struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
272
273   /**
274   * The reference to delete
275   */
276   struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference;
277   /**
278    * Tickets to update
279    */
280   struct TicketRecordsEntry *tickets_to_update_head;
281
282   /**
283    * Tickets to update
284    */
285   struct TicketRecordsEntry *tickets_to_update_tail;
286
287   /**
288    * Attribute label
289    */
290   char *label;
291
292   /**
293    * request id
294    */
295   uint32_t r_id;
296 };
297
298
299 /**
300  * Handle for attribute store request
301  */
302 struct AttributeStoreHandle
303 {
304   /**
305    * DLL
306    */
307   struct AttributeStoreHandle *next;
308
309   /**
310    * DLL
311    */
312   struct AttributeStoreHandle *prev;
313
314   /**
315    * Client connection
316    */
317   struct IdpClient *client;
318
319   /**
320    * Identity
321    */
322   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
323
324   /**
325    * Identity pubkey
326    */
327   struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
328
329   /**
330    * QueueEntry
331    */
332   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
333
334   /**
335    * The attribute to store
336    */
337   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
338
339   /**
340   * The attestation to store
341   */
342   struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
343
344   /**
345   * The reference to store
346   */
347   struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference;
348
349   /**
350    * The attribute expiration interval
351    */
352   struct GNUNET_TIME_Relative exp;
353
354   /**
355    * request id
356    */
357   uint32_t r_id;
358 };
359
360
361 /**
362  * Handle for ticket consume request
363  */
364 struct ConsumeTicketOperation
365 {
366   /**
367    * DLL
368    */
369   struct ConsumeTicketOperation *next;
370
371   /**
372    * DLL
373    */
374   struct ConsumeTicketOperation *prev;
375
376   /**
377    * Client connection
378    */
379   struct IdpClient *client;
380
381   /**
382    * request id
383    */
384   uint32_t r_id;
385
386   /**
387    * Ticket consume handle
388    */
389   struct RECLAIM_TICKETS_ConsumeHandle *ch;
390 };
391
392
393 /**
394  * Ticket revocation request handle
395  */
396 struct TicketRevocationOperation
397 {
398   /**
399    * DLL
400    */
401   struct TicketRevocationOperation *prev;
402
403   /**
404    * DLL
405    */
406   struct TicketRevocationOperation *next;
407
408   /**
409    * Client connection
410    */
411   struct IdpClient *client;
412
413   /**
414    * Revocation handle
415    */
416   struct RECLAIM_TICKETS_RevokeHandle *rh;
417
418   /**
419    * request id
420    */
421   uint32_t r_id;
422 };
423
424
425 /**
426  * Ticket issue operation handle
427  */
428 struct TicketIssueOperation
429 {
430   /**
431    * DLL
432    */
433   struct TicketIssueOperation *prev;
434
435   /**
436    * DLL
437    */
438   struct TicketIssueOperation *next;
439
440   /**
441    * Client connection
442    */
443   struct IdpClient *client;
444
445   /**
446    * request id
447    */
448   uint32_t r_id;
449 };
450
451
452 /**
453  * Client list
454  */
455 static struct IdpClient *client_list_head = NULL;
456
457 /**
458  * Client list
459  */
460 static struct IdpClient *client_list_tail = NULL;
461
462
463 /**
464  * Cleanup attribute delete handle
465  *
466  * @param adh the attribute to cleanup
467  */
468 static void
469 cleanup_adh (struct AttributeDeleteHandle *adh)
470 {
471   struct TicketRecordsEntry *le;
472
473   if (NULL != adh->ns_it)
474     GNUNET_NAMESTORE_zone_iteration_stop (adh->ns_it);
475   if (NULL != adh->ns_qe)
476     GNUNET_NAMESTORE_cancel (adh->ns_qe);
477   if (NULL != adh->label)
478     GNUNET_free (adh->label);
479   if (NULL != adh->claim)
480     GNUNET_free (adh->claim);
481   if (NULL != adh->attest)
482     GNUNET_free (adh->attest);
483   if (NULL != adh->reference)
484     GNUNET_free (adh->reference);
485   while (NULL != (le = adh->tickets_to_update_head))
486   {
487     GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
488                                  adh->tickets_to_update_tail,
489                                  le);
490     if (NULL != le->label)
491       GNUNET_free (le->label);
492     if (NULL != le->data)
493       GNUNET_free (le->data);
494     GNUNET_free (le);
495   }
496   GNUNET_free (adh);
497 }
498
499
500 /**
501  * Cleanup attribute store handle
502  *
503  * @param handle handle to clean up
504  */
505 static void
506 cleanup_as_handle (struct AttributeStoreHandle *ash)
507 {
508   if (NULL != ash->ns_qe)
509     GNUNET_NAMESTORE_cancel (ash->ns_qe);
510   if (NULL != ash->claim)
511     GNUNET_free (ash->claim);
512   if (NULL != ash->attest)
513     GNUNET_free (ash->attest);
514   if (NULL != ash->reference)
515     GNUNET_free (ash->reference);
516   GNUNET_free (ash);
517 }
518
519
520 /**
521  * Cleanup client
522  *
523  * @param idp the client to clean up
524  */
525 static void
526 cleanup_client (struct IdpClient *idp)
527 {
528   struct AttributeIterator *ai;
529   struct TicketIteration *ti;
530   struct TicketRevocationOperation *rop;
531   struct TicketIssueOperation *iss;
532   struct ConsumeTicketOperation *ct;
533   struct AttributeStoreHandle *as;
534   struct AttributeDeleteHandle *adh;
535
536   while (NULL != (iss = idp->issue_op_head))
537   {
538     GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, idp->issue_op_tail, iss);
539     GNUNET_free (iss);
540   }
541   while (NULL != (ct = idp->consume_op_head))
542   {
543     GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
544                                  idp->consume_op_tail,
545                                  ct);
546     if (NULL != ct->ch)
547       RECLAIM_TICKETS_consume_cancel (ct->ch);
548     GNUNET_free (ct);
549   }
550   while (NULL != (as = idp->store_op_head))
551   {
552     GNUNET_CONTAINER_DLL_remove (idp->store_op_head, idp->store_op_tail, as);
553     cleanup_as_handle (as);
554   }
555   while (NULL != (adh = idp->delete_op_head))
556   {
557     GNUNET_CONTAINER_DLL_remove (idp->delete_op_head, idp->delete_op_tail, adh);
558     cleanup_adh (adh);
559   }
560
561   while (NULL != (ai = idp->attr_iter_head))
562   {
563     GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
564     GNUNET_free (ai);
565   }
566   while (NULL != (rop = idp->revoke_op_head))
567   {
568     GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, idp->revoke_op_tail, rop);
569     if (NULL != rop->rh)
570       RECLAIM_TICKETS_revoke_cancel (rop->rh);
571     GNUNET_free (rop);
572   }
573   while (NULL != (ti = idp->ticket_iter_head))
574   {
575     GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
576                                  idp->ticket_iter_tail,
577                                  ti);
578     if (NULL != ti->iter)
579       RECLAIM_TICKETS_iteration_stop (ti->iter);
580     GNUNET_free (ti);
581   }
582   GNUNET_free (idp);
583 }
584
585
586 /**
587  * Cleanup task
588  */
589 static void
590 cleanup ()
591 {
592   struct IdpClient *cl;
593
594   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
595
596   while (NULL != (cl = client_list_head))
597   {
598     GNUNET_CONTAINER_DLL_remove (client_list_head,
599                                  client_list_tail,
600                                  cl);
601     cleanup_client (cl);
602   }
603   RECLAIM_TICKETS_deinit ();
604   if (NULL != timeout_task)
605     GNUNET_SCHEDULER_cancel (timeout_task);
606   if (NULL != nsh)
607     GNUNET_NAMESTORE_disconnect (nsh);
608 }
609
610
611 /**
612  * Shutdown task
613  *
614  * @param cls NULL
615  */
616 static void
617 do_shutdown (void *cls)
618 {
619   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
620   cleanup ();
621 }
622
623
624 /**
625  * Sends a ticket result message to the client
626  *
627  * @param client the client to send to
628  * @param r_id the request message ID to reply to
629  * @param ticket the ticket to include (may be NULL)
630  * @param success the success status of the request
631  */
632 static void
633 send_ticket_result (const struct IdpClient *client,
634                     uint32_t r_id,
635                     const struct GNUNET_RECLAIM_Ticket *ticket,
636                     uint32_t success)
637 {
638   struct TicketResultMessage *irm;
639   struct GNUNET_MQ_Envelope *env;
640
641   env = GNUNET_MQ_msg (irm,
642                        GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
643   if (NULL != ticket)
644   {
645     irm->ticket = *ticket;
646   }
647   // TODO add success member
648   irm->id = htonl (r_id);
649   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
650   GNUNET_MQ_send (client->mq, env);
651 }
652
653
654 /**
655  * Issue ticket result
656  *
657  * @param cls out ticket issue operation handle
658  * @param ticket the issued ticket
659  * @param success issue success status (GNUNET_OK if successful)
660  * @param emsg error message (NULL of success is GNUNET_OK)
661  */
662 static void
663 issue_ticket_result_cb (void *cls,
664                         struct GNUNET_RECLAIM_Ticket *ticket,
665                         int32_t success,
666                         const char *emsg)
667 {
668   struct TicketIssueOperation *tio = cls;
669
670   if (GNUNET_OK != success)
671   {
672     send_ticket_result (tio->client, tio->r_id, NULL, GNUNET_SYSERR);
673     GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
674                                  tio->client->issue_op_tail,
675                                  tio);
676     GNUNET_free (tio);
677     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
678     return;
679   }
680   send_ticket_result (tio->client, tio->r_id, ticket, GNUNET_SYSERR);
681   GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
682                                tio->client->issue_op_tail,
683                                tio);
684   GNUNET_free (tio);
685 }
686
687
688 /**
689  * Check issue ticket message
690  *
691  * @cls unused
692  * @im message to check
693  * @return GNUNET_OK if message is ok
694  */
695 static int
696 check_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
697 {
698   uint16_t size;
699
700   size = ntohs (im->header.size);
701   if (size <= sizeof(struct IssueTicketMessage))
702   {
703     GNUNET_break (0);
704     return GNUNET_SYSERR;
705   }
706   return GNUNET_OK;
707 }
708
709
710 /**
711  * Handle ticket issue message
712  *
713  * @param cls our client
714  * @param im the message
715  */
716 static void
717 handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
718 {
719   struct TicketIssueOperation *tio;
720   struct IdpClient *idp = cls;
721   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
722   size_t attrs_len;
723
724   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ISSUE_TICKET message\n");
725   tio = GNUNET_new (struct TicketIssueOperation);
726   attrs_len = ntohs (im->attr_len);
727   attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char *) &im[1],
728                                                      attrs_len);
729   tio->r_id = ntohl (im->id);
730   tio->client = idp;
731   GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
732   RECLAIM_TICKETS_issue (&im->identity,
733                          attrs,
734                          &im->rp,
735                          &issue_ticket_result_cb,
736                          tio);
737   GNUNET_SERVICE_client_continue (idp->client);
738   GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
739 }
740
741
742 /**********************************************************
743 * Revocation
744 **********************************************************/
745
746 /**
747  * Handles revocation result
748  *
749  * @param cls our revocation operation handle
750  * @param success revocation result (GNUNET_OK if successful)
751  */
752 static void
753 revoke_result_cb (void *cls, int32_t success)
754 {
755   struct TicketRevocationOperation *rop = cls;
756   struct GNUNET_MQ_Envelope *env;
757   struct RevokeTicketResultMessage *trm;
758
759   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
760               "Sending REVOKE_TICKET_RESULT message\n");
761   rop->rh = NULL;
762   env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
763   trm->id = htonl (rop->r_id);
764   trm->success = htonl (success);
765   GNUNET_MQ_send (rop->client->mq, env);
766   GNUNET_CONTAINER_DLL_remove (rop->client->revoke_op_head,
767                                rop->client->revoke_op_tail,
768                                rop);
769   GNUNET_free (rop);
770 }
771
772
773 /**
774  * Check revocation message format
775  *
776  * @param cls unused
777  * @param im the message to check
778  * @return GNUNET_OK if message is ok
779  */
780 static int
781 check_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *im)
782 {
783   uint16_t size;
784
785   size = ntohs (im->header.size);
786   if (size != sizeof(struct RevokeTicketMessage))
787   {
788     GNUNET_break (0);
789     return GNUNET_SYSERR;
790   }
791   return GNUNET_OK;
792 }
793
794
795 /**
796  * Handle a revocation message to a ticket.
797  *
798  * @param cls our client
799  * @param rm the message to handle
800  */
801 static void
802 handle_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *rm)
803 {
804   struct TicketRevocationOperation *rop;
805   struct IdpClient *idp = cls;
806
807   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REVOKE_TICKET message\n");
808   rop = GNUNET_new (struct TicketRevocationOperation);
809   rop->r_id = ntohl (rm->id);
810   rop->client = idp;
811   GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, idp->revoke_op_tail, rop);
812   rop->rh
813     = RECLAIM_TICKETS_revoke (&rm->ticket, &rm->identity, &revoke_result_cb,
814                               rop);
815   GNUNET_SERVICE_client_continue (idp->client);
816 }
817
818
819 /**
820  * Handle a ticket consume result
821  *
822  * @param cls our consume ticket operation handle
823  * @param identity the attribute authority
824  * @param attrs the attribute/claim list
825  * @param success GNUNET_OK if successful
826  * @param emsg error message (NULL if success=GNUNET_OK)
827  */
828 static void
829 consume_result_cb (void *cls,
830                    const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
831                    const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
832                    int32_t success,
833                    const char *emsg)
834 {
835   struct ConsumeTicketOperation *cop = cls;
836   struct ConsumeTicketResultMessage *crm;
837   struct GNUNET_MQ_Envelope *env;
838   char *data_tmp;
839   size_t attrs_len;
840
841   if (GNUNET_OK != success)
842   {
843     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
844   }
845   attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
846   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
847               "Sending CONSUME_TICKET_RESULT message\n");
848   env = GNUNET_MQ_msg_extra (crm,
849                              attrs_len,
850                              GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
851   crm->id = htonl (cop->r_id);
852   crm->attrs_len = htons (attrs_len);
853   crm->identity = *identity;
854   crm->result = htonl (success);
855   data_tmp = (char *) &crm[1];
856   GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, data_tmp);
857   GNUNET_MQ_send (cop->client->mq, env);
858   GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
859                                cop->client->consume_op_tail,
860                                cop);
861   GNUNET_free (cop);
862 }
863
864
865 /**
866  * Check a consume ticket message
867  *
868  * @param cls unused
869  * @param cm the message to handle
870  */
871 static int
872 check_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
873 {
874   uint16_t size;
875
876   size = ntohs (cm->header.size);
877   if (size != sizeof(struct ConsumeTicketMessage))
878   {
879     GNUNET_break (0);
880     return GNUNET_SYSERR;
881   }
882   return GNUNET_OK;
883 }
884
885
886 /**
887  * Handle a consume ticket message
888  *
889  * @param cls our client handle
890  * @cm the message to handle
891  */
892 static void
893 handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
894 {
895   struct ConsumeTicketOperation *cop;
896   struct IdpClient *idp = cls;
897
898   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CONSUME_TICKET message\n");
899   cop = GNUNET_new (struct ConsumeTicketOperation);
900   cop->r_id = ntohl (cm->id);
901   cop->client = idp;
902   cop->ch
903     = RECLAIM_TICKETS_consume (&cm->identity, &cm->ticket, &consume_result_cb,
904                                cop);
905   GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, idp->consume_op_tail, cop);
906   GNUNET_SERVICE_client_continue (idp->client);
907 }
908
909
910 /*****************************************
911 * Attribute store
912 *****************************************/
913
914
915 /**
916  * Attribute store result handler
917  *
918  * @param cls our attribute store handle
919  * @param success GNUNET_OK if successful
920  * @param emsg error message (NULL if success=GNUNET_OK)
921  */
922 static void
923 attr_store_cont (void *cls, int32_t success, const char *emsg)
924 {
925   struct AttributeStoreHandle *ash = cls;
926   struct GNUNET_MQ_Envelope *env;
927   struct SuccessResultMessage *acr_msg;
928
929   ash->ns_qe = NULL;
930   GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
931                                ash->client->store_op_tail,
932                                ash);
933
934   if (GNUNET_SYSERR == success)
935   {
936     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
937                 "Failed to store attribute %s\n",
938                 emsg);
939     cleanup_as_handle (ash);
940     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
941     return;
942   }
943
944   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
945   env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
946   acr_msg->id = htonl (ash->r_id);
947   acr_msg->op_result = htonl (GNUNET_OK);
948   GNUNET_MQ_send (ash->client->mq, env);
949   cleanup_as_handle (ash);
950 }
951
952
953 /**
954  * Add a new attribute
955  *
956  * @param cls the AttributeStoreHandle
957  */
958 static void
959 attr_store_task (void *cls)
960 {
961   struct AttributeStoreHandle *ash = cls;
962   struct GNUNET_GNSRECORD_Data rd[1];
963   char *buf;
964   char *label;
965   size_t buf_size;
966
967   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attribute\n");
968   buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (ash->claim);
969   buf = GNUNET_malloc (buf_size);
970   // Give the ash a new id if unset
971   if (0 == ash->claim->id)
972     ash->claim->id
973       = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
974   GNUNET_RECLAIM_ATTRIBUTE_serialize (ash->claim, buf);
975   label
976     = GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id, sizeof(uint64_t));
977   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
978
979   rd[0].data_size = buf_size;
980   rd[0].data = buf;
981   rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR;
982   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
983   rd[0].expiration_time = ash->exp.rel_value_us;
984   ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
985                                                &ash->identity,
986                                                label,
987                                                1,
988                                                rd,
989                                                &attr_store_cont,
990                                                ash);
991   GNUNET_free (buf);
992   GNUNET_free (label);
993 }
994
995
996 /**
997  * Check an attribute store message
998  *
999  * @param cls unused
1000  * @param sam the message to check
1001  */
1002 static int
1003 check_attribute_store_message (void *cls,
1004                                const struct AttributeStoreMessage *sam)
1005 {
1006   uint16_t size;
1007
1008   size = ntohs (sam->header.size);
1009   if (size <= sizeof(struct AttributeStoreMessage))
1010   {
1011     GNUNET_break (0);
1012     return GNUNET_SYSERR;
1013   }
1014   return GNUNET_OK;
1015 }
1016
1017
1018 /**
1019  * Handle an attribute store message
1020  *
1021  * @param cls our client
1022  * @param sam the message to handle
1023  */
1024 static void
1025 handle_attribute_store_message (void *cls,
1026                                 const struct AttributeStoreMessage *sam)
1027 {
1028   struct AttributeStoreHandle *ash;
1029   struct IdpClient *idp = cls;
1030   size_t data_len;
1031
1032   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_STORE message\n");
1033
1034   data_len = ntohs (sam->attr_len);
1035
1036   ash = GNUNET_new (struct AttributeStoreHandle);
1037   ash->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *) &sam[1],
1038                                                      data_len);
1039
1040   ash->r_id = ntohl (sam->id);
1041   ash->identity = sam->identity;
1042   ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1043   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
1044
1045   GNUNET_SERVICE_client_continue (idp->client);
1046   ash->client = idp;
1047   GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1048   GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1049 }
1050
1051
1052 /**
1053  * Attestation store result handler
1054  *
1055  * @param cls our attribute store handle
1056  * @param success GNUNET_OK if successful
1057  * @param emsg error message (NULL if success=GNUNET_OK)
1058  */
1059 static void
1060 attest_store_cont (void *cls, int32_t success, const char *emsg)
1061 {
1062   struct AttributeStoreHandle *ash = cls;
1063   struct GNUNET_MQ_Envelope *env;
1064   struct SuccessResultMessage *acr_msg;
1065
1066   ash->ns_qe = NULL;
1067   GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1068                                ash->client->store_op_tail,
1069                                ash);
1070
1071   if (GNUNET_SYSERR == success)
1072   {
1073     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1074                 "Failed to store attestation %s\n",
1075                 emsg);
1076     cleanup_as_handle (ash);
1077     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1078     return;
1079   }
1080
1081   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1082   env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1083   acr_msg->id = htonl (ash->r_id);
1084   acr_msg->op_result = htonl (GNUNET_OK);
1085   GNUNET_MQ_send (ash->client->mq, env);
1086   cleanup_as_handle (ash);
1087 }
1088
1089 /**
1090      * Send a reference error response
1091      *
1092      * @param ash our attribute store handle
1093      * @param success the success status
1094      */
1095 static void
1096 send_ref_error (struct AttributeStoreHandle  *ash)
1097 {
1098   struct GNUNET_MQ_Envelope *env;
1099   struct SuccessResultMessage *acr_msg;
1100
1101   ash->ns_qe = NULL;
1102   GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1103                                ash->client->store_op_tail,
1104                                ash);
1105
1106   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1107   env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1108   acr_msg->id = htonl (ash->r_id);
1109   acr_msg->op_result = htonl (GNUNET_SYSERR);
1110   GNUNET_MQ_send (ash->client->mq, env);
1111   cleanup_as_handle (ash);
1112 }
1113
1114 /**
1115  * Error looking up potential attestation. Abort.
1116  *
1117  * @param cls our attribute store handle
1118  */
1119 static void
1120 attest_error (void *cls)
1121 {
1122   struct AttributeStoreHandle *ash = cls;
1123   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1124               "Failed to check for existing Attestation\n");
1125   cleanup_as_handle (ash);
1126   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1127   return;
1128 }
1129
1130 /**
1131 * Check for existing record before storing reference
1132 *
1133 * @param cls our attribute store handle
1134 * @param zone zone we are iterating
1135 * @param label label of the records
1136 * @param rd_count record count
1137 * @param rd records
1138 */
1139 static void
1140 attest_add_cb (void *cls,
1141                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1142                const char *label,
1143                unsigned int rd_count,
1144                const struct GNUNET_GNSRECORD_Data *rd)
1145 {
1146   struct AttributeStoreHandle *ash = cls;
1147   char *buf;
1148   size_t buf_size;
1149   buf_size = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (ash->attest);
1150   buf = GNUNET_malloc (buf_size);
1151   GNUNET_RECLAIM_ATTESTATION_serialize (ash->attest, buf);
1152   if (0 == rd_count )
1153   {
1154     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1155                 "Storing new Attestation\n");
1156     struct GNUNET_GNSRECORD_Data rd_new[1];
1157     rd_new[0].data_size = buf_size;
1158     rd_new[0].data = buf;
1159     rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR;
1160     rd_new[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1161     rd_new[0].expiration_time = ash->exp.rel_value_us;
1162     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1163     ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1164                                                  &ash->identity,
1165                                                  label,
1166                                                  1,
1167                                                  rd_new,
1168                                                  &attest_store_cont,
1169                                                  ash);
1170     GNUNET_free (buf);
1171     return;
1172   }
1173   if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[0].record_type)
1174   {
1175     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1176                 "Existing Attestation location is not an Attestation\n");
1177     send_ref_error (ash);
1178     return;
1179   }
1180   struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1181   for (int i = 0; i<rd_count; i++)
1182   {
1183     rd_new[i] = rd[i];
1184   }
1185   rd_new[0].data_size = buf_size;
1186   rd_new[0].data = buf;
1187   rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR;
1188   rd_new[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1189   rd_new[0].expiration_time = ash->exp.rel_value_us;
1190   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1191   ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1192                                                &ash->identity,
1193                                                label,
1194                                                rd_count,
1195                                                rd_new,
1196                                                &attest_store_cont,
1197                                                ash);
1198   GNUNET_free (buf);
1199 }
1200
1201 /**
1202  * Add a new attestation
1203  *
1204  * @param cls the AttributeStoreHandle
1205  */
1206 static void
1207 attest_store_task (void *cls)
1208 {
1209   struct AttributeStoreHandle *ash = cls;
1210   char *label;
1211
1212   // Give the ash a new id if unset
1213   if (0 == ash->attest->id)
1214     ash->attest->id
1215       = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
1216   label = GNUNET_STRINGS_data_to_string_alloc (&ash->attest->id,
1217                                                sizeof(uint64_t));
1218   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1219               "Looking up existing data under label %s\n", label);
1220 // Test for the content of the existing ID
1221   ash->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
1222                                                 &ash->identity,
1223                                                 label,
1224                                                 &attest_error,
1225                                                 ash,
1226                                                 &attest_add_cb,
1227                                                 ash);
1228   GNUNET_free (label);
1229 }
1230
1231 /**
1232  * Check an attestation store message
1233  *
1234  * @param cls unused
1235  * @param sam the message to check
1236  */
1237 static int
1238 check_attestation_store_message (void *cls,
1239                                  const struct AttributeStoreMessage *sam)
1240 {
1241   uint16_t size;
1242
1243   size = ntohs (sam->header.size);
1244   if (size <= sizeof(struct AttributeStoreMessage))
1245   {
1246     GNUNET_break (0);
1247     return GNUNET_SYSERR;
1248   }
1249   return GNUNET_OK;
1250 }
1251
1252 /**
1253 * Handle an attestation store message
1254 *
1255 * @param cls our client
1256 * @param sam the message to handle
1257 */
1258 static void
1259 handle_attestation_store_message (void *cls,
1260                                   const struct AttributeStoreMessage *sam)
1261 {
1262   struct AttributeStoreHandle *ash;
1263   struct IdpClient *idp = cls;
1264   size_t data_len;
1265
1266   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_STORE message\n");
1267
1268   data_len = ntohs (sam->attr_len);
1269
1270   ash = GNUNET_new (struct AttributeStoreHandle);
1271   ash->attest = GNUNET_RECLAIM_ATTESTATION_deserialize ((char *) &sam[1],
1272                                                         data_len);
1273
1274   ash->r_id = ntohl (sam->id);
1275   ash->identity = sam->identity;
1276   ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1277   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
1278
1279   GNUNET_SERVICE_client_continue (idp->client);
1280   ash->client = idp;
1281   GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1282   GNUNET_SCHEDULER_add_now (&attest_store_task, ash);
1283 }
1284
1285 /**
1286  * Error looking up potential reference value. Abort.
1287  *
1288  * @param cls our attribute store handle
1289  */
1290 static void
1291 ref_error (void *cls)
1292 {
1293   struct AttributeStoreHandle *ash = cls;
1294   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1295               "Failed to find Attestation entry for Attestation reference\n");
1296   cleanup_as_handle (ash);
1297   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1298   return;
1299 }
1300
1301 /**
1302  * Error looking up potential reference value. Abort.
1303  *
1304  * @param cls our attribute delete handle
1305  */
1306 static void
1307 ref_del_error (void *cls)
1308 {
1309   struct AttributeDeleteHandle *adh = cls;
1310   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1311               "Failed to find Attestation entry for Attestation reference\n");
1312   cleanup_adh (adh);
1313   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1314   return;
1315 }
1316 /**
1317 * Reference store result handler
1318 *
1319 * @param cls our attribute store handle
1320 * @param success GNUNET_OK if successful
1321 * @param emsg error message (NULL if success=GNUNET_OK)
1322 */
1323 static void
1324 reference_store_cont (void *cls, int32_t success, const char *emsg)
1325 {
1326   struct AttributeStoreHandle *ash = cls;
1327   struct GNUNET_MQ_Envelope *env;
1328   struct SuccessResultMessage *acr_msg;
1329
1330   ash->ns_qe = NULL;
1331   GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1332                                ash->client->store_op_tail,
1333                                ash);
1334
1335   if (GNUNET_SYSERR == success)
1336   {
1337     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1338                 "Failed to store reference %s\n",
1339                 emsg);
1340     cleanup_as_handle (ash);
1341     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1342     return;
1343   }
1344
1345   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1346   env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1347   acr_msg->id = htonl (ash->r_id);
1348   acr_msg->op_result = htonl (GNUNET_OK);
1349   GNUNET_MQ_send (ash->client->mq, env);
1350   cleanup_as_handle (ash);
1351 }
1352
1353
1354 /**
1355 * Check for existing record before storing reference
1356 *
1357 * @param cls our attribute store handle
1358 * @param zone zone we are iterating
1359 * @param label label of the records
1360 * @param rd_count record count
1361 * @param rd records
1362 */
1363 static void
1364 ref_add_cb (void *cls,
1365             const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1366             const char *label,
1367             unsigned int rd_count,
1368             const struct GNUNET_GNSRECORD_Data *rd)
1369 {
1370   struct AttributeStoreHandle *ash = cls;
1371   char *buf;
1372   size_t buf_size;
1373   buf_size = GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (ash->reference);
1374   buf = GNUNET_malloc (buf_size);
1375   GNUNET_RECLAIM_ATTESTATION_REF_serialize (ash->reference, buf);
1376   struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *ref;
1377   char *data_tmp;
1378   if (0 == rd_count )
1379   {
1380     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1381                 "Failed to find Attestation entry for Attestation reference\n");
1382     send_ref_error (ash);
1383     return;
1384   }
1385   if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[0].record_type)
1386   {
1387     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1388                 "Intended Reference storage location is not an attestation\n");
1389     send_ref_error (ash);
1390     return;
1391   }
1392   struct GNUNET_GNSRECORD_Data rd_new[rd_count + 1];
1393   int i;
1394   for (i = 0; i<rd_count; i++)
1395   {
1396     data_tmp = GNUNET_malloc (rd[i].data_size);
1397     GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
1398     ref = GNUNET_RECLAIM_ATTESTATION_REF_deserialize (data_tmp, htons (
1399                                                         rd[i].data_size));
1400     rd_new[i] = rd[i];
1401     if ((strcmp (ash->reference->name,ref->name) == 0)&&
1402         (strcmp (ash->reference->reference_value,ref->reference_value)==0) )
1403     {
1404       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1405                   "Reference already stored\n");
1406       reference_store_cont (ash,GNUNET_OK, NULL);
1407       return;
1408     }
1409   }
1410   rd_new[rd_count].data_size = buf_size;
1411   rd_new[rd_count].data = buf;
1412   rd_new[rd_count].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE;
1413   rd_new[rd_count].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1414   rd_new[rd_count].expiration_time = ash->exp.rel_value_us;
1415   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1416   ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1417                                                &ash->identity,
1418                                                label,
1419                                                rd_count + 1,
1420                                                rd_new,
1421                                                &reference_store_cont,
1422                                                ash);
1423   GNUNET_free (buf);
1424 }
1425
1426 /**
1427  * Add a new reference
1428  *
1429  * @param cls the AttributeStoreHandle
1430  */
1431 static void
1432 reference_store_task (void *cls)
1433 {
1434   struct AttributeStoreHandle *ash = cls;
1435   char *label;
1436
1437   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing reference\n");
1438
1439   // Give the ash a new id if unset
1440   if (0 == ash->reference->id)
1441   {
1442     if (0 == ash->reference->id_attest)
1443     {
1444       ash->reference->id = GNUNET_CRYPTO_random_u64 (
1445         GNUNET_CRYPTO_QUALITY_STRONG,
1446         UINT64_MAX);
1447     }
1448     else
1449     {
1450       ash->reference->id = ash->reference->id_attest;
1451     }
1452   }
1453
1454   label = GNUNET_STRINGS_data_to_string_alloc (&ash->reference->id,
1455                                                sizeof(uint64_t));
1456   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1457               "Looking up existing data under label %s\n", label);
1458 // Test for the content of the existing ID
1459
1460   ash->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
1461                                                 &ash->identity,
1462                                                 label,
1463                                                 &ref_error,
1464                                                 ash,
1465                                                 &ref_add_cb,
1466                                                 ash);
1467   GNUNET_free (label);
1468 }
1469
1470 /**
1471      * Check an attestation reference store message
1472      *
1473      * @param cls unused
1474      * @param sam the message to check
1475      */
1476 static int
1477 check_reference_store_message (void *cls,
1478                                const struct
1479                                AttributeStoreMessage *sam)
1480 {
1481   uint16_t size;
1482
1483   size = ntohs (sam->header.size);
1484   if (size <= sizeof(struct AttributeStoreMessage))
1485   {
1486     GNUNET_break (0);
1487     return GNUNET_SYSERR;
1488   }
1489   return GNUNET_OK;
1490 }
1491
1492
1493 /**
1494     * Handle an attestation reference store message
1495     *
1496     * @param cls our client
1497     * @param sam the message to handle
1498     */
1499 static void
1500 handle_reference_store_message (void *cls,
1501                                 const struct AttributeStoreMessage *sam)
1502 {
1503   struct AttributeStoreHandle *ash;
1504   struct IdpClient *idp = cls;
1505   size_t data_len;
1506
1507   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REFERENCE_STORE message\n");
1508
1509   data_len = ntohs (sam->attr_len);
1510   ash = GNUNET_new (struct AttributeStoreHandle);
1511   ash->reference = GNUNET_RECLAIM_ATTESTATION_REF_deserialize ((char *) &sam[1],
1512                                                                data_len);
1513   ash->r_id = ntohl (sam->id);
1514   ash->identity = sam->identity;
1515   ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1516   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
1517
1518
1519   GNUNET_SERVICE_client_continue (idp->client);
1520   ash->client = idp;
1521   GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1522   GNUNET_SCHEDULER_add_now (&reference_store_task, ash);
1523 }
1524 /**
1525  * Send a deletion success response
1526  *
1527  * @param adh our attribute deletion handle
1528  * @param success the success status
1529  */
1530 static void
1531 send_delete_response (struct AttributeDeleteHandle *adh, int32_t success)
1532 {
1533   struct GNUNET_MQ_Envelope *env;
1534   struct SuccessResultMessage *acr_msg;
1535
1536   GNUNET_CONTAINER_DLL_remove (adh->client->delete_op_head,
1537                                adh->client->delete_op_tail,
1538                                adh);
1539
1540   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1541   env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1542   acr_msg->id = htonl (adh->r_id);
1543   acr_msg->op_result = htonl (success);
1544   GNUNET_MQ_send (adh->client->mq, env);
1545 }
1546
1547
1548 /**
1549  * Namestore iteration within attribute deletion.
1550  * We need to reissue tickets with the deleted attribute removed.
1551  *
1552  * @param cls our attribute deletion handle
1553  * @param zone the private key of the ticket issuer
1554  * @param label the label of the record
1555  * @param rd_count number of records
1556  * @param rd record data
1557  */
1558 static void
1559 ticket_iter (void *cls,
1560              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1561              const char *label,
1562              unsigned int rd_count,
1563              const struct GNUNET_GNSRECORD_Data *rd)
1564 {
1565   struct AttributeDeleteHandle *adh = cls;
1566   struct TicketRecordsEntry *le;
1567   int has_changed = GNUNET_NO;
1568   for (int i = 0; i < rd_count; i++)
1569   {
1570     if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
1571       continue;
1572     if (adh->claim != NULL)
1573       if (0 != memcmp (rd[i].data, &adh->claim->id, sizeof(uint64_t)))
1574         continue;
1575     if (adh->attest != NULL)
1576       if (0 != memcmp (rd[i].data, &adh->attest->id, sizeof(uint64_t)))
1577         continue;
1578     if (adh->reference != NULL)
1579       if (0 != memcmp (rd[i].data, &adh->reference->id, sizeof(uint64_t)))
1580         continue;
1581     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1582                 "Attribute or Attestation/Reference to delete found (%s)\n",
1583                 adh->label);
1584     has_changed = GNUNET_YES;
1585     break;
1586   }
1587   if (GNUNET_YES == has_changed)
1588   {
1589     le = GNUNET_new (struct TicketRecordsEntry);
1590     le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1591     le->data = GNUNET_malloc (le->data_size);
1592     le->rd_count = rd_count;
1593     le->label = GNUNET_strdup (label);
1594     GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
1595     GNUNET_CONTAINER_DLL_insert (adh->tickets_to_update_head,
1596                                  adh->tickets_to_update_tail,
1597                                  le);
1598   }
1599   GNUNET_NAMESTORE_zone_iterator_next (adh->ns_it, 1);
1600 }
1601
1602
1603 /**
1604  * Recursion prototype for function
1605  * @param cls our deletion handle
1606  */
1607 static void
1608 update_tickets (void *cls);
1609
1610
1611 /**
1612  * Callback called when a ticket was updated
1613  *
1614  * @param cls our attribute deletion handle
1615  * @param success GNUNET_OK if successful
1616  * @param emsg error message (NULL if success=GNUNET_OK)
1617  */
1618 static void
1619 ticket_updated (void *cls, int32_t success, const char *emsg)
1620 {
1621   struct AttributeDeleteHandle *adh = cls;
1622
1623   adh->ns_qe = NULL;
1624   GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1625 }
1626
1627
1628 /**
1629  * Update tickets: Remove shared attribute which has just been deleted.
1630  * This method is called recursively until all tickets are processed.
1631  * Eventually, the updated tickets are stored using ``update_tickets''.
1632  *
1633  * @param cls our attribute deletion handle
1634  */
1635 static void
1636 update_tickets (void *cls)
1637 {
1638   struct AttributeDeleteHandle *adh = cls;
1639   struct TicketRecordsEntry *le;
1640
1641   if (NULL == adh->tickets_to_update_head)
1642   {
1643     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1644                 "Finished updating tickets, success\n");
1645     send_delete_response (adh, GNUNET_OK);
1646     cleanup_adh (adh);
1647     return;
1648   }
1649   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1650               "Updating %s\n",
1651               adh->tickets_to_update_head->label);
1652   le = adh->tickets_to_update_head;
1653   GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
1654                                adh->tickets_to_update_tail,
1655                                le);
1656   struct GNUNET_GNSRECORD_Data rd[le->rd_count];
1657   struct GNUNET_GNSRECORD_Data rd_new[le->rd_count - 1];
1658   if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (le->data_size,
1659                                                          le->data,
1660                                                          le->rd_count,
1661                                                          rd))
1662   {
1663     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1664                 "Unable to deserialize record data!\n");
1665     send_delete_response (adh, GNUNET_SYSERR);
1666     cleanup_adh (adh);
1667     return;
1668   }
1669   int j = 0;
1670   for (int i = 0; i < le->rd_count; i++)
1671   {
1672     if (adh->claim != NULL)
1673       if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
1674           && (0 == memcmp (rd[i].data, &adh->claim->id, sizeof(uint64_t))))
1675         continue;
1676     if (adh->attest != NULL)
1677       if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
1678           && (0 == memcmp (rd[i].data, &adh->attest->id, sizeof(uint64_t))))
1679         continue;
1680     if (adh->reference != NULL)
1681       if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
1682           && (0 == memcmp (rd[i].data, &adh->reference->id, sizeof(uint64_t))))
1683         continue;
1684     rd_new[j] = rd[i];
1685     j++;
1686   }
1687   adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1688                                                &adh->identity,
1689                                                le->label,
1690                                                j,
1691                                                rd_new,
1692                                                &ticket_updated,
1693                                                adh);
1694   GNUNET_free (le->label);
1695   GNUNET_free (le->data);
1696   GNUNET_free (le);
1697 }
1698
1699
1700 /**
1701  * Done collecting affected tickets, start updating.
1702  *
1703  * @param cls our attribute deletion handle
1704  */
1705 static void
1706 ticket_iter_fin (void *cls)
1707 {
1708   struct AttributeDeleteHandle *adh = cls;
1709   adh->ns_it = NULL;
1710   GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1711 }
1712
1713
1714 /**
1715  * Error collecting affected tickets. Abort.
1716  *
1717  * @param cls our attribute deletion handle
1718  */
1719 static void
1720 ticket_iter_err (void *cls)
1721 {
1722   struct AttributeDeleteHandle *adh = cls;
1723
1724   adh->ns_it = NULL;
1725   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1726               "Namestore error on delete %s\n",
1727               adh->label);
1728   send_delete_response (adh, GNUNET_SYSERR);
1729   cleanup_adh (adh);
1730 }
1731
1732
1733 /**
1734  * Start processing tickets which may still contain reference to deleted
1735  * attribute.
1736  *
1737  * @param cls attribute deletion handle
1738  */
1739 static void
1740 start_ticket_update (void *cls)
1741 {
1742   struct AttributeDeleteHandle *adh = cls;
1743
1744   adh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1745                                                       &adh->identity,
1746                                                       &ticket_iter_err,
1747                                                       adh,
1748                                                       &ticket_iter,
1749                                                       adh,
1750                                                       &ticket_iter_fin,
1751                                                       adh);
1752 }
1753
1754
1755 /**
1756  * Attribute deleted callback
1757  *
1758  * @param cls our handle
1759  * @param success success status
1760  * @param emsg error message (NULL if success=GNUNET_OK)
1761  */
1762 static void
1763 attr_delete_cont (void *cls, int32_t success, const char *emsg)
1764 {
1765   struct AttributeDeleteHandle *adh = cls;
1766
1767   adh->ns_qe = NULL;
1768   if (GNUNET_SYSERR == success)
1769   {
1770     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1771                 "Error deleting attribute %s\n",
1772                 adh->label);
1773     send_delete_response (adh, GNUNET_SYSERR);
1774     cleanup_adh (adh);
1775     return;
1776   }
1777   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1778   GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1779 }
1780
1781
1782 /**
1783  * Check attribute delete message format
1784  *
1785  * @cls unused
1786  * @dam message to check
1787  */
1788 static int
1789 check_attribute_delete_message (void *cls,
1790                                 const struct AttributeDeleteMessage *dam)
1791 {
1792   uint16_t size;
1793
1794   size = ntohs (dam->header.size);
1795   if (size <= sizeof(struct AttributeDeleteMessage))
1796   {
1797     GNUNET_break (0);
1798     return GNUNET_SYSERR;
1799   }
1800   return GNUNET_OK;
1801 }
1802
1803
1804 /**
1805  * Handle attribute deletion
1806  *
1807  * @param cls our client
1808  * @param dam deletion message
1809  */
1810 static void
1811 handle_attribute_delete_message (void *cls,
1812                                  const struct AttributeDeleteMessage *dam)
1813 {
1814   struct AttributeDeleteHandle *adh;
1815   struct IdpClient *idp = cls;
1816   size_t data_len;
1817
1818   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_DELETE message\n");
1819
1820   data_len = ntohs (dam->attr_len);
1821
1822   adh = GNUNET_new (struct AttributeDeleteHandle);
1823   adh->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *) &dam[1],
1824                                                      data_len);
1825   adh->reference = NULL;
1826   adh->attest = NULL;
1827
1828   adh->r_id = ntohl (dam->id);
1829   adh->identity = dam->identity;
1830   adh->label
1831     = GNUNET_STRINGS_data_to_string_alloc (&adh->claim->id, sizeof(uint64_t));
1832   GNUNET_SERVICE_client_continue (idp->client);
1833   adh->client = idp;
1834   GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1835   adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1836                                                &adh->identity,
1837                                                adh->label,
1838                                                0,
1839                                                NULL,
1840                                                &attr_delete_cont,
1841                                                adh);
1842 }
1843
1844 /**
1845    * Attestation deleted callback
1846    *
1847    * @param cls our handle
1848    * @param success success status
1849    * @param emsg error message (NULL if success=GNUNET_OK)
1850    */
1851 static void
1852 attest_delete_cont (void *cls, int32_t success, const char *emsg)
1853 {
1854   struct AttributeDeleteHandle *adh = cls;
1855
1856   adh->ns_qe = NULL;
1857   if (GNUNET_SYSERR == success)
1858   {
1859     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1860                 "Error deleting attestation %s\n",
1861                 adh->label);
1862     send_delete_response (adh, GNUNET_SYSERR);
1863     cleanup_adh (adh);
1864     return;
1865   }
1866   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1867   GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1868 }
1869
1870 /**
1871  * Check attestation delete message format
1872  *
1873  * @cls unused
1874  * @dam message to check
1875  */
1876 static int
1877 check_attestation_delete_message (void *cls,
1878                                   const struct AttributeDeleteMessage *dam)
1879 {
1880   uint16_t size;
1881
1882   size = ntohs (dam->header.size);
1883   if (size <= sizeof(struct AttributeDeleteMessage))
1884   {
1885     GNUNET_break (0);
1886     return GNUNET_SYSERR;
1887   }
1888   return GNUNET_OK;
1889 }
1890
1891
1892 /**
1893  * Handle attestation deletion
1894  *
1895  * @param cls our client
1896  * @param dam deletion message
1897  */
1898 static void
1899 handle_attestation_delete_message (void *cls,
1900                                    const struct AttributeDeleteMessage *dam)
1901 {
1902   struct AttributeDeleteHandle *adh;
1903   struct IdpClient *idp = cls;
1904   size_t data_len;
1905
1906   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_DELETE message\n");
1907
1908   data_len = ntohs (dam->attr_len);
1909
1910   adh = GNUNET_new (struct AttributeDeleteHandle);
1911   adh->attest = GNUNET_RECLAIM_ATTESTATION_deserialize ((char *) &dam[1],
1912                                                         data_len);
1913   adh->reference = NULL;
1914   adh->claim = NULL;
1915
1916   adh->r_id = ntohl (dam->id);
1917   adh->identity = dam->identity;
1918   adh->label
1919     = GNUNET_STRINGS_data_to_string_alloc (&adh->attest->id, sizeof(uint64_t));
1920   GNUNET_SERVICE_client_continue (idp->client);
1921   adh->client = idp;
1922   GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1923   adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1924                                                &adh->identity,
1925                                                adh->label,
1926                                                0,
1927                                                NULL,
1928                                                &attest_delete_cont,
1929                                                adh);
1930 }
1931
1932
1933
1934 /**
1935 * Reference deleted callback
1936 *
1937 * @param cls our handle
1938 * @param success success status
1939 * @param emsg error message (NULL if success=GNUNET_OK)
1940 */
1941 static void
1942 reference_delete_cont (void *cls, int32_t success, const char *emsg)
1943 {
1944   struct AttributeDeleteHandle *adh = cls;
1945
1946   adh->ns_qe = NULL;
1947   if (GNUNET_SYSERR == success)
1948   {
1949     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1950                 "Error deleting reference %s\n",
1951                 adh->label);
1952     send_delete_response (adh, GNUNET_SYSERR);
1953     cleanup_adh (adh);
1954     return;
1955   }
1956   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1957   //GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1958   send_delete_response (adh, GNUNET_OK);
1959   cleanup_adh (adh);
1960   return;
1961 }
1962
1963 static void
1964 ref_del_cb (void *cls,
1965             const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1966             const char *label,
1967             unsigned int rd_count,
1968             const struct GNUNET_GNSRECORD_Data *rd)
1969 {
1970
1971   struct AttributeDeleteHandle *adh = cls;
1972   char *data_tmp;
1973   struct GNUNET_GNSRECORD_Data rd_new[rd_count - 1];
1974   struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *ref;
1975   size_t attr_len;
1976
1977   if (0 == rd_count )
1978   {
1979     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1980                 "Failed to find Attestation entry for Attestation reference\n");
1981     cleanup_adh (adh);
1982     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1983     return;
1984   }
1985   if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[0].record_type)
1986   {
1987     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1988                 "Intended Reference location is not an attestation\n");
1989     cleanup_adh (adh);
1990     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1991     return;
1992   }
1993   rd_new[0] = rd[0];
1994   int i;
1995   int j = 1;
1996   for (i = 1; i<rd_count; i++)
1997   {
1998     data_tmp = GNUNET_malloc (rd[i].data_size);
1999     GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
2000     attr_len = htons (rd[i].data_size);
2001     ref = GNUNET_RECLAIM_ATTESTATION_REF_deserialize (data_tmp, attr_len);
2002     if (NULL == ref )
2003     {
2004       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2005                   "Unable to parse attestation reference from %s\n",
2006                   data_tmp);
2007       rd_new[j] = rd[i];
2008       j += 1;
2009       continue;
2010     }
2011     if ((strcmp (adh->reference->name,ref->name) == 0)&&
2012         (strcmp (adh->reference->reference_value,ref->reference_value)==0) )
2013     {
2014       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2015                   "Found reference to delete.\n");
2016     }
2017     else
2018     {
2019       rd_new[j] = rd[i];
2020       j += 1;
2021     }
2022     GNUNET_free (data_tmp);
2023   }
2024   adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
2025                                                &adh->identity,
2026                                                label,
2027                                                j,
2028                                                rd_new,
2029                                                &reference_delete_cont,
2030                                                adh);
2031 }
2032
2033 /**
2034  * Check an attestation reference delete message
2035  *
2036  * @param cls unused
2037  * @param sam the message to check
2038  */
2039 static int
2040 check_reference_delete_message (void *cls,
2041                                 const struct AttributeDeleteMessage *dam)
2042 {
2043   uint16_t size;
2044
2045   size = ntohs (dam->header.size);
2046   if (size <= sizeof(struct AttributeDeleteMessage))
2047   {
2048     GNUNET_break (0);
2049     return GNUNET_SYSERR;
2050   }
2051   return GNUNET_OK;
2052 }
2053
2054 /**
2055  * Handle reference deletion
2056  *
2057  * @param cls our client
2058  * @param dam deletion message
2059  */
2060 static void
2061 handle_reference_delete_message (void *cls,
2062                                  const struct AttributeDeleteMessage *dam)
2063 {
2064   struct AttributeDeleteHandle *adh;
2065   struct IdpClient *idp = cls;
2066   size_t data_len;
2067
2068   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REFERENCE_DELETE message\n");
2069   data_len = ntohs (dam->attr_len);
2070   adh = GNUNET_new (struct AttributeDeleteHandle);
2071   adh->reference = GNUNET_RECLAIM_ATTESTATION_REF_deserialize ((char *) &dam[1],
2072                                                                data_len);
2073   adh->attest = NULL;
2074   adh->claim = NULL;
2075
2076   adh->r_id = ntohl (dam->id);
2077   adh->identity = dam->identity;
2078   adh->label
2079     = GNUNET_STRINGS_data_to_string_alloc (&adh->reference->id,
2080                                            sizeof(uint64_t));
2081   GNUNET_SERVICE_client_continue (idp->client);
2082   adh->client = idp;
2083   GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
2084   adh->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
2085                                                 &adh->identity,
2086                                                 adh->label,
2087                                                 &ref_del_error,
2088                                                 adh,
2089                                                 &ref_del_cb,
2090                                                 adh);
2091 }
2092
2093
2094
2095 /*************************************************
2096 * Attrubute iteration
2097 *************************************************/
2098
2099
2100 /**
2101  * Done iterating over attributes
2102  *
2103  * @param cls our iterator handle
2104  */
2105 static void
2106 attr_iter_finished (void *cls)
2107 {
2108   struct AttributeIterator *ai = cls;
2109   struct GNUNET_MQ_Envelope *env;
2110   struct AttributeResultMessage *arm;
2111
2112   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
2113   env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
2114   arm->id = htonl (ai->request_id);
2115   arm->attr_len = htons (0);
2116   GNUNET_MQ_send (ai->client->mq, env);
2117   GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
2118                                ai->client->attr_iter_tail,
2119                                ai);
2120   GNUNET_free (ai);
2121 }
2122
2123
2124 /**
2125  * Error iterating over attributes. Abort.
2126  *
2127  * @param cls our attribute iteration handle
2128  */
2129 static void
2130 attr_iter_error (void *cls)
2131 {
2132   struct AttributeIterator *ai = cls;
2133
2134   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
2135   attr_iter_finished (ai);
2136 }
2137
2138
2139 /**
2140  * Got record. Return if it is an attribute or attestation/reference.
2141  *
2142  * @param cls our attribute iterator
2143  * @param zone zone we are iterating
2144  * @param label label of the records
2145  * @param rd_count record count
2146  * @param rd records
2147  */
2148 static void
2149 attr_iter_cb (void *cls,
2150               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
2151               const char *label,
2152               unsigned int rd_count,
2153               const struct GNUNET_GNSRECORD_Data *rd)
2154 {
2155   struct AttributeIterator *ai = cls;
2156   struct GNUNET_MQ_Envelope *env;
2157   char *data_tmp;
2158
2159   if (rd_count == 0)
2160   {
2161     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2162     return;
2163   }
2164   if (rd_count > 1)
2165   {
2166     if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[0].record_type)
2167     {
2168       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2169                   "Found Ticket. Ignoring.\n");
2170       GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2171       return;
2172     }
2173     else if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[0].record_type)
2174     {
2175       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2176                   "Non-Attestation record with multiple entries found: %u\n",
2177                   rd[0].record_type);
2178       GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2179       return;
2180     }
2181   }
2182
2183   for (int i = 0; i<rd_count; i++)
2184   {
2185     if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd[i].record_type) &&
2186         (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[i].record_type) &&
2187         (GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE != rd[i].record_type))
2188     {
2189       GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2190       return;
2191     }
2192
2193     if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR == rd[i].record_type )
2194     {
2195       struct AttributeResultMessage *arm;
2196       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n",
2197                   label);
2198       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2199                   "Sending ATTRIBUTE_RESULT message\n");
2200       env = GNUNET_MQ_msg_extra (arm,
2201                                  rd[i].data_size,
2202                                  GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
2203       arm->id = htonl (ai->request_id);
2204       arm->attr_len = htons (rd[i].data_size);
2205       GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
2206       data_tmp = (char *) &arm[1];
2207       GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
2208       GNUNET_MQ_send (ai->client->mq, env);
2209     }
2210     else
2211     {
2212       if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR == rd[i].record_type )
2213       {
2214         struct AttributeResultMessage *arm;
2215         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attestation under: %s\n",
2216                     label);
2217         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2218                     "Sending ATTESTATION_RESULT message\n");
2219         env = GNUNET_MQ_msg_extra (arm,
2220                                    rd[i].data_size,
2221                                    GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT);
2222         arm->id = htonl (ai->request_id);
2223         arm->attr_len = htons (rd[i].data_size);
2224         GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
2225         data_tmp = (char *) &arm[1];
2226         GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
2227         GNUNET_MQ_send (ai->client->mq, env);
2228       }
2229       else
2230       {
2231         struct ReferenceResultMessage *rrm;
2232         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found reference under: %s\n",
2233                     label);
2234         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2235                     "Sending REFERENCE_RESULT message\n");
2236         env = GNUNET_MQ_msg_extra (rrm,
2237                                    rd[i].data_size + rd[0].data_size,
2238                                    GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_RESULT);
2239         rrm->id = htonl (ai->request_id);
2240         rrm->attest_len = htons (rd[0].data_size);
2241         rrm->ref_len = htons (rd[i].data_size);
2242         GNUNET_CRYPTO_ecdsa_key_get_public (zone, &rrm->identity);
2243         data_tmp = (char *) &rrm[1];
2244         GNUNET_memcpy (data_tmp, rd[0].data, rd[0].data_size);
2245         data_tmp += rd[0].data_size;
2246         GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
2247         GNUNET_MQ_send (ai->client->mq, env);
2248       }
2249     }
2250   }
2251 }
2252
2253 /**
2254  * Iterate over zone to get attributes
2255  *
2256  * @param cls our client
2257  * @param ais_msg the iteration message to start
2258  */
2259 static void
2260 handle_iteration_start (void *cls,
2261                         const struct AttributeIterationStartMessage *ais_msg)
2262 {
2263   struct IdpClient *idp = cls;
2264   struct AttributeIterator *ai;
2265
2266   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2267               "Received ATTRIBUTE_ITERATION_START message\n");
2268   ai = GNUNET_new (struct AttributeIterator);
2269   ai->request_id = ntohl (ais_msg->id);
2270   ai->client = idp;
2271   ai->identity = ais_msg->identity;
2272
2273   GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
2274   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
2275                                                      &ai->identity,
2276                                                      &attr_iter_error,
2277                                                      ai,
2278                                                      &attr_iter_cb,
2279                                                      ai,
2280                                                      &attr_iter_finished,
2281                                                      ai);
2282   GNUNET_SERVICE_client_continue (idp->client);
2283 }
2284
2285
2286 /**
2287  * Handle iteration stop message from client
2288  *
2289  * @param cls the client
2290  * @param ais_msg the stop message
2291  */
2292 static void
2293 handle_iteration_stop (void *cls,
2294                        const struct AttributeIterationStopMessage *ais_msg)
2295 {
2296   struct IdpClient *idp = cls;
2297   struct AttributeIterator *ai;
2298   uint32_t rid;
2299
2300   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2301               "Received `%s' message\n",
2302               "ATTRIBUTE_ITERATION_STOP");
2303   rid = ntohl (ais_msg->id);
2304   for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
2305     if (ai->request_id == rid)
2306       break;
2307   if (NULL == ai)
2308   {
2309     GNUNET_break (0);
2310     GNUNET_SERVICE_client_drop (idp->client);
2311     return;
2312   }
2313   GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
2314   GNUNET_free (ai);
2315   GNUNET_SERVICE_client_continue (idp->client);
2316 }
2317
2318
2319 /**
2320  * Client requests next attribute from iterator
2321  *
2322  * @param cls the client
2323  * @param ais_msg the message
2324  */
2325 static void
2326 handle_iteration_next (void *cls,
2327                        const struct AttributeIterationNextMessage *ais_msg)
2328 {
2329   struct IdpClient *idp = cls;
2330   struct AttributeIterator *ai;
2331   uint32_t rid;
2332
2333   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2334               "Received ATTRIBUTE_ITERATION_NEXT message\n");
2335   rid = ntohl (ais_msg->id);
2336   for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
2337     if (ai->request_id == rid)
2338       break;
2339   if (NULL == ai)
2340   {
2341     GNUNET_break (0);
2342     GNUNET_SERVICE_client_drop (idp->client);
2343     return;
2344   }
2345   GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2346   GNUNET_SERVICE_client_continue (idp->client);
2347 }
2348
2349
2350 /******************************************************
2351 * Ticket iteration
2352 ******************************************************/
2353
2354 /**
2355  * Got a ticket. Return to client
2356  *
2357  * @param cls our ticket iterator
2358  * @param ticket the ticket
2359  */
2360 static void
2361 ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket)
2362 {
2363   struct TicketIteration *ti = cls;
2364   struct GNUNET_MQ_Envelope *env;
2365   struct TicketResultMessage *trm;
2366
2367   env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
2368   if (NULL == ticket)
2369   {
2370     /* send empty response to indicate end of list */
2371     GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2372                                  ti->client->ticket_iter_tail,
2373                                  ti);
2374   }
2375   else
2376   {
2377     trm->ticket = *ticket;
2378   }
2379   trm->id = htonl (ti->r_id);
2380   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
2381   GNUNET_MQ_send (ti->client->mq, env);
2382   if (NULL == ticket)
2383     GNUNET_free (ti);
2384 }
2385
2386
2387 /**
2388  * Client requests a ticket iteration
2389  *
2390  * @param cls the client
2391  * @param tis_msg the iteration request message
2392  */
2393 static void
2394 handle_ticket_iteration_start (
2395   void *cls,
2396   const struct TicketIterationStartMessage *tis_msg)
2397 {
2398   struct IdpClient *client = cls;
2399   struct TicketIteration *ti;
2400
2401   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2402               "Received TICKET_ITERATION_START message\n");
2403   ti = GNUNET_new (struct TicketIteration);
2404   ti->r_id = ntohl (tis_msg->id);
2405   ti->client = client;
2406
2407   GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2408                                client->ticket_iter_tail,
2409                                ti);
2410   ti->iter
2411     = RECLAIM_TICKETS_iteration_start (&tis_msg->identity, &ticket_iter_cb, ti);
2412   GNUNET_SERVICE_client_continue (client->client);
2413 }
2414
2415
2416 /**
2417  * Client has had enough tickets
2418  *
2419  * @param cls the client
2420  * @param tis_msg the stop message
2421  */
2422 static void
2423 handle_ticket_iteration_stop (void *cls,
2424                               const struct TicketIterationStopMessage *tis_msg)
2425 {
2426   struct IdpClient *client = cls;
2427   struct TicketIteration *ti;
2428   uint32_t rid;
2429
2430   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2431               "Received `%s' message\n",
2432               "TICKET_ITERATION_STOP");
2433   rid = ntohl (tis_msg->id);
2434   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2435     if (ti->r_id == rid)
2436       break;
2437   if (NULL == ti)
2438   {
2439     GNUNET_break (0);
2440     GNUNET_SERVICE_client_drop (client->client);
2441     return;
2442   }
2443   RECLAIM_TICKETS_iteration_stop (ti->iter);
2444   GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2445                                client->ticket_iter_tail,
2446                                ti);
2447   GNUNET_free (ti);
2448   GNUNET_SERVICE_client_continue (client->client);
2449 }
2450
2451
2452 /**
2453  * Client requests next result.
2454  *
2455  * @param cls the client
2456  * @param tis_msg the message
2457  */
2458 static void
2459 handle_ticket_iteration_next (void *cls,
2460                               const struct TicketIterationNextMessage *tis_msg)
2461 {
2462   struct IdpClient *client = cls;
2463   struct TicketIteration *ti;
2464   uint32_t rid;
2465
2466   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2467               "Received TICKET_ITERATION_NEXT message\n");
2468   rid = ntohl (tis_msg->id);
2469   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2470     if (ti->r_id == rid)
2471       break;
2472   if (NULL == ti)
2473   {
2474     GNUNET_break (0);
2475     GNUNET_SERVICE_client_drop (client->client);
2476     return;
2477   }
2478   RECLAIM_TICKETS_iteration_next (ti->iter);
2479   GNUNET_SERVICE_client_continue (client->client);
2480 }
2481
2482
2483 /**
2484  * Main function that will be run
2485  *
2486  * @param cls closure
2487  * @param c the configuration used
2488  * @param server the service handle
2489  */
2490 static void
2491 run (void *cls,
2492      const struct GNUNET_CONFIGURATION_Handle *c,
2493      struct GNUNET_SERVICE_Handle *server)
2494 {
2495   cfg = c;
2496
2497   if (GNUNET_OK != RECLAIM_TICKETS_init (cfg))
2498   {
2499     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2500                 "Unable to initialize TICKETS subsystem.\n");
2501     GNUNET_SCHEDULER_shutdown ();
2502     return;
2503   }
2504   // Connect to identity and namestore services
2505   nsh = GNUNET_NAMESTORE_connect (cfg);
2506   if (NULL == nsh)
2507   {
2508     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
2509                          "error connecting to namestore");
2510   }
2511
2512   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2513 }
2514
2515
2516 /**
2517  * Called whenever a client is disconnected.
2518  *
2519  * @param cls closure
2520  * @param client identification of the client
2521  * @param app_ctx @a client
2522  */
2523 static void
2524 client_disconnect_cb (void *cls,
2525                       struct GNUNET_SERVICE_Client *client,
2526                       void *app_ctx)
2527 {
2528   struct IdpClient *idp = app_ctx;
2529
2530   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
2531   GNUNET_CONTAINER_DLL_remove (client_list_head,
2532                                client_list_tail,
2533                                idp);
2534   cleanup_client (idp);
2535 }
2536
2537
2538 /**
2539  * Add a client to our list of active clients.
2540  *
2541  * @param cls NULL
2542  * @param client client to add
2543  * @param mq message queue for @a client
2544  * @return internal namestore client structure for this client
2545  */
2546 static void *
2547 client_connect_cb (void *cls,
2548                    struct GNUNET_SERVICE_Client *client,
2549                    struct GNUNET_MQ_Handle *mq)
2550 {
2551   struct IdpClient *idp;
2552
2553   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
2554   idp = GNUNET_new (struct IdpClient);
2555   idp->client = client;
2556   idp->mq = mq;
2557   GNUNET_CONTAINER_DLL_insert (client_list_head,
2558                                client_list_tail,
2559                                idp);
2560   return idp;
2561 }
2562
2563
2564 /**
2565  * Define "main" method using service macro.
2566  */
2567 GNUNET_SERVICE_MAIN (
2568   "reclaim",
2569   GNUNET_SERVICE_OPTION_NONE,
2570   &run,
2571   &client_connect_cb,
2572   &client_disconnect_cb,
2573   NULL,
2574   GNUNET_MQ_hd_var_size (attribute_store_message,
2575                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
2576                          struct AttributeStoreMessage,
2577                          NULL),
2578   GNUNET_MQ_hd_var_size (attestation_store_message,
2579                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE,
2580                          struct AttributeStoreMessage,
2581                          NULL),
2582   GNUNET_MQ_hd_var_size (attribute_delete_message,
2583                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
2584                          struct AttributeDeleteMessage,
2585                          NULL),
2586   GNUNET_MQ_hd_var_size (attestation_delete_message,
2587                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE,
2588                          struct AttributeDeleteMessage,
2589                          NULL),
2590   GNUNET_MQ_hd_var_size (reference_store_message,
2591                          GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_STORE,
2592                          struct AttributeStoreMessage,
2593                          NULL),
2594   GNUNET_MQ_hd_var_size (reference_delete_message,
2595                          GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_DELETE,
2596                          struct AttributeDeleteMessage,
2597                          NULL),
2598   GNUNET_MQ_hd_fixed_size (
2599     iteration_start,
2600     GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
2601     struct AttributeIterationStartMessage,
2602     NULL),
2603   GNUNET_MQ_hd_fixed_size (iteration_next,
2604                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
2605                            struct AttributeIterationNextMessage,
2606                            NULL),
2607   GNUNET_MQ_hd_fixed_size (iteration_stop,
2608                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
2609                            struct AttributeIterationStopMessage,
2610                            NULL),
2611   GNUNET_MQ_hd_var_size (issue_ticket_message,
2612                          GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
2613                          struct IssueTicketMessage,
2614                          NULL),
2615   GNUNET_MQ_hd_var_size (consume_ticket_message,
2616                          GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
2617                          struct ConsumeTicketMessage,
2618                          NULL),
2619   GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
2620                            GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
2621                            struct TicketIterationStartMessage,
2622                            NULL),
2623   GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2624                            GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
2625                            struct TicketIterationNextMessage,
2626                            NULL),
2627   GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2628                            GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
2629                            struct TicketIterationStopMessage,
2630                            NULL),
2631   GNUNET_MQ_hd_var_size (revoke_ticket_message,
2632                          GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
2633                          struct RevokeTicketMessage,
2634                          NULL),
2635   GNUNET_MQ_handler_end ());
2636 /* end of gnunet-service-reclaim.c */