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