aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim/gnunet-service-reclaim.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/reclaim/gnunet-service-reclaim.c')
-rw-r--r--src/reclaim/gnunet-service-reclaim.c2786
1 files changed, 2786 insertions, 0 deletions
diff --git a/src/reclaim/gnunet-service-reclaim.c b/src/reclaim/gnunet-service-reclaim.c
new file mode 100644
index 000000000..3321a79d8
--- /dev/null
+++ b/src/reclaim/gnunet-service-reclaim.c
@@ -0,0 +1,2786 @@
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/**
19 * @author Martin Schanzenbach
20 * @file src/reclaim/gnunet-service-reclaim.c
21 * @brief reclaim Service
22 *
23 */
24#include "platform.h"
25#include "gnunet_util_lib.h"
26#include "gnunet_constants.h"
27#include "gnunet_protocols.h"
28#include "gnunet_identity_service.h"
29#include "gnunet_gnsrecord_lib.h"
30#include "gnunet_namestore_service.h"
31#include "gnunet_abe_lib.h"
32#include "gnunet_credential_service.h"
33#include "gnunet_statistics_service.h"
34#include "gnunet_gns_service.h"
35#include "gnunet_reclaim_plugin.h"
36#include "gnunet_reclaim_attribute_lib.h"
37#include "gnunet_signatures.h"
38#include "reclaim.h"
39
40/**
41 * First pass state
42 */
43#define STATE_INIT 0
44
45/**
46 * Normal operation state
47 */
48#define STATE_POST_INIT 1
49
50/**
51 * Minimum interval between updates
52 */
53#define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
54
55/**
56 * Standard token expiration time
57 */
58#define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
59
60/**
61 * Identity handle
62 */
63static struct GNUNET_IDENTITY_Handle *identity_handle;
64
65/**
66 * Database handle
67 */
68static struct GNUNET_RECLAIM_PluginFunctions *TKT_database;
69
70/**
71 * Name of DB plugin
72 */
73static char *db_lib_name;
74
75/**
76 * Token expiration interval
77 */
78static struct GNUNET_TIME_Relative token_expiration_interval;
79
80/**
81 * Namestore handle
82 */
83static struct GNUNET_NAMESTORE_Handle *ns_handle;
84
85/**
86 * GNS handle
87 */
88static struct GNUNET_GNS_Handle *gns_handle;
89
90/**
91 * Credential handle
92 */
93static struct GNUNET_CREDENTIAL_Handle *credential_handle;
94
95/**
96 * Namestore qe
97 */
98static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
99
100/**
101 * Namestore iterator
102 */
103static struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
104
105/**
106 * Timeout task
107 */
108static struct GNUNET_SCHEDULER_Task *timeout_task;
109
110/**
111 * Update task
112 */
113static struct GNUNET_SCHEDULER_Task *update_task;
114
115
116/**
117 * Currently processed token
118 */
119static struct IdentityToken *token;
120
121/**
122 * Label for currently processed token
123 */
124static char* label;
125
126/**
127 * Scopes for processed token
128 */
129static char* scopes;
130
131/**
132 * Handle to the statistics service.
133 */
134static struct GNUNET_STATISTICS_Handle *stats;
135
136/**
137 * Our configuration.
138 */
139static const struct GNUNET_CONFIGURATION_Handle *cfg;
140
141/**
142 * An idp client
143 */
144struct IdpClient;
145
146/**
147 * A ticket iteration operation.
148 */
149struct TicketIteration
150{
151 /**
152 * DLL
153 */
154 struct TicketIteration *next;
155
156 /**
157 * DLL
158 */
159 struct TicketIteration *prev;
160
161 /**
162 * Client which intiated this zone iteration
163 */
164 struct IdpClient *client;
165
166 /**
167 * Key of the identity we are iterating over.
168 */
169 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
170
171 /**
172 * Identity is audience
173 */
174 uint32_t is_audience;
175
176 /**
177 * The operation id fot the iteration in the response for the client
178 */
179 uint32_t r_id;
180
181 /**
182 * Offset of the iteration used to address next result of the
183 * iteration in the store
184 *
185 * Initialy set to 0 in handle_iteration_start
186 * Incremented with by every call to handle_iteration_next
187 */
188 uint32_t offset;
189
190};
191
192
193
194/**
195 * Callback after an ABE bootstrap
196 *
197 * @param cls closure
198 * @param abe_key the ABE key that exists or was created
199 */
200typedef void
201(*AbeBootstrapResult) (void *cls,
202 struct GNUNET_ABE_AbeMasterKey *abe_key);
203
204
205struct AbeBootstrapHandle
206{
207 /**
208 * Function to call when finished
209 */
210 AbeBootstrapResult proc;
211
212 /**
213 * Callback closure
214 */
215 char *proc_cls;
216
217 /**
218 * Key of the zone we are iterating over.
219 */
220 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
221
222 /**
223 * Namestore Queue Entry
224 */
225 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
226
227 /**
228 * The issuer egos ABE master key
229 */
230 struct GNUNET_ABE_AbeMasterKey *abe_key;
231};
232
233/**
234 * An attribute iteration operation.
235 */
236struct AttributeIterator
237{
238 /**
239 * Next element in the DLL
240 */
241 struct AttributeIterator *next;
242
243 /**
244 * Previous element in the DLL
245 */
246 struct AttributeIterator *prev;
247
248 /**
249 * IDP client which intiated this zone iteration
250 */
251 struct IdpClient *client;
252
253 /**
254 * Key of the zone we are iterating over.
255 */
256 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
257
258 /**
259 * The issuer egos ABE master key
260 */
261 struct GNUNET_ABE_AbeMasterKey *abe_key;
262
263 /**
264 * Namestore iterator
265 */
266 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
267
268 /**
269 * The operation id fot the zone iteration in the response for the client
270 */
271 uint32_t request_id;
272
273};
274
275
276
277/**
278 * An idp client
279 */
280struct IdpClient
281{
282
283 /**
284 * The client
285 */
286 struct GNUNET_SERVICE_Client *client;
287
288 /**
289 * Message queue for transmission to @e client
290 */
291 struct GNUNET_MQ_Handle *mq;
292
293 /**
294 * Head of the DLL of
295 * Attribute iteration operations in
296 * progress initiated by this client
297 */
298 struct AttributeIterator *attr_iter_head;
299
300 /**
301 * Tail of the DLL of
302 * Attribute iteration operations
303 * in progress initiated by this client
304 */
305 struct AttributeIterator *attr_iter_tail;
306
307 /**
308 * Head of DLL of ticket iteration ops
309 */
310 struct TicketIteration *ticket_iter_head;
311
312 /**
313 * Tail of DLL of ticket iteration ops
314 */
315 struct TicketIteration *ticket_iter_tail;
316
317 /**
318 * Head of DLL of ticket revocation ops
319 */
320 struct TicketRevocationHandle *revoke_op_head;
321
322 /**
323 * Tail of DLL of ticket revocation ops
324 */
325 struct TicketRevocationHandle *revoke_op_tail;
326
327 /**
328 * Head of DLL of ticket issue ops
329 */
330 struct TicketIssueHandle *issue_op_head;
331
332 /**
333 * Tail of DLL of ticket issue ops
334 */
335 struct TicketIssueHandle *issue_op_tail;
336
337 /**
338 * Head of DLL of ticket consume ops
339 */
340 struct ConsumeTicketHandle *consume_op_head;
341
342 /**
343 * Tail of DLL of ticket consume ops
344 */
345 struct ConsumeTicketHandle *consume_op_tail;
346
347 /**
348 * Head of DLL of attribute store ops
349 */
350 struct AttributeStoreHandle *store_op_head;
351
352 /**
353 * Tail of DLL of attribute store ops
354 */
355 struct AttributeStoreHandle *store_op_tail;
356
357};
358
359struct AttributeStoreHandle
360{
361 /**
362 * DLL
363 */
364 struct AttributeStoreHandle *next;
365
366 /**
367 * DLL
368 */
369 struct AttributeStoreHandle *prev;
370
371 /**
372 * Client connection
373 */
374 struct IdpClient *client;
375
376 /**
377 * Identity
378 */
379 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
380
381 /**
382 * Identity pubkey
383 */
384 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
385
386 /**
387 * The issuer egos ABE master key
388 */
389 struct GNUNET_ABE_AbeMasterKey *abe_key;
390
391 /**
392 * QueueEntry
393 */
394 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
395
396 /**
397 * The attribute to store
398 */
399 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
400
401 /**
402 * The attribute expiration interval
403 */
404 struct GNUNET_TIME_Relative exp;
405
406 /**
407 * request id
408 */
409 uint32_t r_id;
410};
411
412
413/* Prototype */
414struct ParallelLookup;
415
416struct ConsumeTicketHandle
417{
418 /**
419 * DLL
420 */
421 struct ConsumeTicketHandle *next;
422
423 /**
424 * DLL
425 */
426 struct ConsumeTicketHandle *prev;
427
428 /**
429 * Client connection
430 */
431 struct IdpClient *client;
432
433 /**
434 * Ticket
435 */
436 struct GNUNET_RECLAIM_Ticket ticket;
437
438 /**
439 * LookupRequest
440 */
441 struct GNUNET_GNS_LookupRequest *lookup_request;
442
443 /**
444 * Audience Key
445 */
446 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
447
448 /**
449 * Audience Key
450 */
451 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
452
453 /**
454 * Lookup DLL
455 */
456 struct ParallelLookup *parallel_lookups_head;
457
458 /**
459 * Lookup DLL
460 */
461 struct ParallelLookup *parallel_lookups_tail;
462
463 /**
464 * Kill task
465 */
466 struct GNUNET_SCHEDULER_Task *kill_task;
467
468 /**
469 * The ABE key
470 */
471 struct GNUNET_ABE_AbeKey *key;
472
473 /**
474 * Attributes
475 */
476 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
477
478 /**
479 * Lookup time
480 */
481 struct GNUNET_TIME_Absolute lookup_start_time;
482
483 /**
484 * request id
485 */
486 uint32_t r_id;
487};
488
489/**
490 * Handle for a parallel GNS lookup job
491 */
492struct ParallelLookup
493{
494 /* DLL */
495 struct ParallelLookup *next;
496
497 /* DLL */
498 struct ParallelLookup *prev;
499
500 /* The GNS request */
501 struct GNUNET_GNS_LookupRequest *lookup_request;
502
503 /* The handle the return to */
504 struct ConsumeTicketHandle *handle;
505
506 /**
507 * Lookup time
508 */
509 struct GNUNET_TIME_Absolute lookup_start_time;
510
511 /* The label to look up */
512 char *label;
513};
514
515/**
516 * Ticket revocation request handle
517 */
518struct TicketRevocationHandle
519{
520 /**
521 * DLL
522 */
523 struct TicketRevocationHandle *prev;
524
525 /**
526 * DLL
527 */
528 struct TicketRevocationHandle *next;
529
530 /**
531 * Client connection
532 */
533 struct IdpClient *client;
534
535 /**
536 * Attributes to reissue
537 */
538 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
539
540 /**
541 * Attributes to revoke
542 */
543 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *rvk_attrs;
544
545 /**
546 * Issuer Key
547 */
548 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
549
550 /**
551 * Ticket to issue
552 */
553 struct GNUNET_RECLAIM_Ticket ticket;
554
555 /**
556 * QueueEntry
557 */
558 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
559
560 /**
561 * Namestore iterator
562 */
563 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
564
565 /**
566 * The ABE master key
567 */
568 struct GNUNET_ABE_AbeMasterKey *abe_key;
569
570 /**
571 * Offset
572 */
573 uint32_t offset;
574
575 /**
576 * request id
577 */
578 uint32_t r_id;
579};
580
581
582
583/**
584 * Ticket issue request handle
585 */
586struct TicketIssueHandle
587{
588 /**
589 * DLL
590 */
591 struct TicketIssueHandle *prev;
592
593 /**
594 * DLL
595 */
596 struct TicketIssueHandle *next;
597
598 /**
599 * Client connection
600 */
601 struct IdpClient *client;
602
603 /**
604 * Attributes to issue
605 */
606 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
607
608 /**
609 * Issuer Key
610 */
611 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
612
613 /**
614 * Ticket to issue
615 */
616 struct GNUNET_RECLAIM_Ticket ticket;
617
618 /**
619 * QueueEntry
620 */
621 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
622
623 /**
624 * request id
625 */
626 uint32_t r_id;
627};
628
629
630/**
631 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
632 *
633 */
634struct EgoEntry
635{
636 /**
637 * DLL
638 */
639 struct EgoEntry *next;
640
641 /**
642 * DLL
643 */
644 struct EgoEntry *prev;
645
646 /**
647 * Ego handle
648 */
649 struct GNUNET_IDENTITY_Ego *ego;
650
651 /**
652 * Attribute map. Contains the attributes as json_t
653 */
654 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
655
656};
657
658/**
659 * Cleanup task
660 */
661static void
662cleanup()
663{
664 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
665 "Cleaning up\n");
666
667 if (NULL != stats)
668 {
669 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
670 stats = NULL;
671 }
672 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
673 TKT_database));
674 GNUNET_free (db_lib_name);
675 db_lib_name = NULL;
676 if (NULL != timeout_task)
677 GNUNET_SCHEDULER_cancel (timeout_task);
678 if (NULL != update_task)
679 GNUNET_SCHEDULER_cancel (update_task);
680 if (NULL != identity_handle)
681 GNUNET_IDENTITY_disconnect (identity_handle);
682 if (NULL != gns_handle)
683 GNUNET_GNS_disconnect (gns_handle);
684 if (NULL != credential_handle)
685 GNUNET_CREDENTIAL_disconnect (credential_handle);
686 if (NULL != ns_it)
687 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
688 if (NULL != ns_qe)
689 GNUNET_NAMESTORE_cancel (ns_qe);
690 if (NULL != ns_handle)
691 GNUNET_NAMESTORE_disconnect (ns_handle);
692 GNUNET_free_non_null (token);
693 GNUNET_free_non_null (label);
694
695}
696
697/**
698 * Shutdown task
699 *
700 * @param cls NULL
701 */
702static void
703do_shutdown (void *cls)
704{
705 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
706 "Shutting down...\n");
707 cleanup();
708}
709
710/**
711 * Finished storing newly bootstrapped ABE key
712 */
713static void
714bootstrap_store_cont (void *cls,
715 int32_t success,
716 const char *emsg)
717{
718 struct AbeBootstrapHandle *abh = cls;
719 if (GNUNET_SYSERR == success)
720 {
721 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
722 "Failed to bootstrap ABE master %s\n",
723 emsg);
724 abh->proc (abh->proc_cls, NULL);
725 GNUNET_free (abh->abe_key);
726 GNUNET_free (abh);
727 return;
728 }
729 abh->proc (abh->proc_cls, abh->abe_key);
730 GNUNET_free (abh);
731}
732
733/**
734 * Generates and stores a new ABE key
735 */
736static void
737bootstrap_store_task (void *cls)
738{
739 struct AbeBootstrapHandle *abh = cls;
740 struct GNUNET_GNSRECORD_Data rd[1];
741 char *key;
742
743 rd[0].data_size = GNUNET_ABE_cpabe_serialize_master_key (abh->abe_key,
744 (void**)&key);
745 rd[0].data = key;
746 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
747 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
748 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
749 abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
750 &abh->identity,
751 "+",
752 1,
753 rd,
754 &bootstrap_store_cont,
755 abh);
756 GNUNET_free (key);
757}
758
759/**
760 * Error checking for ABE master
761 */
762static void
763bootstrap_abe_error (void *cls)
764{
765 struct AbeBootstrapHandle *abh = cls;
766 abh->proc (abh->proc_cls, NULL);
767 GNUNET_free (abh);
768}
769
770
771/**
772 * Handle ABE lookup in namestore
773 */
774static void
775bootstrap_abe_result (void *cls,
776 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
777 const char *label,
778 unsigned int rd_count,
779 const struct GNUNET_GNSRECORD_Data *rd)
780{
781 struct AbeBootstrapHandle *abh = cls;
782 struct GNUNET_ABE_AbeMasterKey *abe_key;
783
784 for (uint32_t i=0;i<rd_count;i++) {
785 if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
786 continue;
787 abe_key = GNUNET_ABE_cpabe_deserialize_master_key (rd[i].data,
788 rd[i].data_size);
789 abh->proc (abh->proc_cls, abe_key);
790 GNUNET_free (abh);
791 return;
792 }
793
794 //No ABE master found, bootstrapping...
795 abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
796 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
797}
798
799/**
800 * Bootstrap ABE master if it does not yet exists.
801 * Will call the AbeBootstrapResult processor when done.
802 * will always recreate the ABE key of GNUNET_YES == recreate
803 */
804static void
805bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
806 AbeBootstrapResult proc,
807 void* cls,
808 int recreate)
809{
810 struct AbeBootstrapHandle *abh;
811
812 abh = GNUNET_new (struct AbeBootstrapHandle);
813 abh->proc = proc;
814 abh->proc_cls = cls;
815 abh->identity = *identity;
816 if (GNUNET_YES == recreate)
817 {
818 abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
819 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
820 } else {
821 abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
822 identity,
823 "+",
824 &bootstrap_abe_error,
825 abh,
826 &bootstrap_abe_result,
827 abh);
828 }
829}
830
831
832
833static int
834create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
835 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
836 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
837{
838 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
839
840 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
841 &new_key_hash_str);
842 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
843 static const char ctx_key[] = "gnuid-aes-ctx-key";
844 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
845 new_key_hash, sizeof (struct GNUNET_HashCode),
846 ctx_key, strlen (ctx_key),
847 NULL, 0);
848 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
849 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
850 new_key_hash, sizeof (struct GNUNET_HashCode),
851 ctx_iv, strlen (ctx_iv),
852 NULL, 0);
853 return GNUNET_OK;
854}
855
856/**
857 * Cleanup ticket consume handle
858 * @param handle the handle to clean up
859 */
860static void
861cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
862{
863 if (NULL != handle->attrs)
864 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (handle->attrs);
865 if (NULL != handle->ns_qe)
866 GNUNET_NAMESTORE_cancel (handle->ns_qe);
867 GNUNET_free (handle);
868}
869
870
871static void
872send_ticket_result (struct IdpClient *client,
873 uint32_t r_id,
874 const struct GNUNET_RECLAIM_Ticket *ticket,
875 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
876{
877 struct TicketResultMessage *irm;
878 struct GNUNET_MQ_Envelope *env;
879 struct GNUNET_RECLAIM_Ticket *ticket_buf;
880
881 /* store ticket in DB */
882 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
883 ticket,
884 attrs))
885 {
886 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
887 "Unable to store ticket after issue\n");
888 GNUNET_break (0);
889 }
890
891 env = GNUNET_MQ_msg_extra (irm,
892 sizeof (struct GNUNET_RECLAIM_Ticket),
893 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
894 ticket_buf = (struct GNUNET_RECLAIM_Ticket *)&irm[1];
895 *ticket_buf = *ticket;
896 irm->id = htonl (r_id);
897 GNUNET_MQ_send (client->mq,
898 env);
899}
900
901static void
902store_ticket_issue_cont (void *cls,
903 int32_t success,
904 const char *emsg)
905{
906 struct TicketIssueHandle *handle = cls;
907
908 handle->ns_qe = NULL;
909 GNUNET_CONTAINER_DLL_remove (handle->client->issue_op_head,
910 handle->client->issue_op_tail,
911 handle);
912 if (GNUNET_SYSERR == success)
913 {
914 cleanup_ticket_issue_handle (handle);
915 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
916 "Unknown Error\n");
917 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
918 return;
919 }
920 send_ticket_result (handle->client,
921 handle->r_id,
922 &handle->ticket,
923 handle->attrs);
924 cleanup_ticket_issue_handle (handle);
925}
926
927
928
929int
930serialize_abe_keyinfo2 (const struct GNUNET_RECLAIM_Ticket *ticket,
931 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
932 const struct GNUNET_ABE_AbeKey *rp_key,
933 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
934 char **result)
935{
936 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
937 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
938 char *enc_keyinfo;
939 char *serialized_key;
940 char *buf;
941 char *write_ptr;
942 char attrs_str_len;
943 ssize_t size;
944
945 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
946 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
947 struct GNUNET_HashCode new_key_hash;
948 ssize_t enc_size;
949
950 size = GNUNET_ABE_cpabe_serialize_key (rp_key,
951 (void**)&serialized_key);
952 attrs_str_len = 0;
953 for (le = attrs->list_head; NULL != le; le = le->next) {
954 attrs_str_len += strlen (le->claim->name) + 1;
955 }
956 buf = GNUNET_malloc (attrs_str_len + size);
957 write_ptr = buf;
958 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
959 "Writing attributes\n");
960 for (le = attrs->list_head; NULL != le; le = le->next) {
961 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
962 "%s\n", le->claim->name);
963
964
965 GNUNET_memcpy (write_ptr,
966 le->claim->name,
967 strlen (le->claim->name));
968 write_ptr[strlen (le->claim->name)] = ',';
969 write_ptr += strlen (le->claim->name) + 1;
970 }
971 write_ptr--;
972 write_ptr[0] = '\0'; //replace last , with a 0-terminator
973 write_ptr++;
974 GNUNET_memcpy (write_ptr,
975 serialized_key,
976 size);
977 GNUNET_free (serialized_key);
978 // ECDH keypair E = eG
979 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
980 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
981 &ecdh_pubkey);
982 enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
983 // Derived key K = H(eB)
984 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
985 &ticket->audience,
986 &new_key_hash));
987 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
988 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
989 size + attrs_str_len,
990 &skey, &iv,
991 enc_keyinfo);
992 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
993 enc_size);
994 GNUNET_memcpy (*result,
995 &ecdh_pubkey,
996 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
997 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
998 enc_keyinfo,
999 enc_size);
1000 GNUNET_free (enc_keyinfo);
1001 GNUNET_free (buf);
1002 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
1003}
1004
1005
1006
1007static void
1008issue_ticket_after_abe_bootstrap (void *cls,
1009 struct GNUNET_ABE_AbeMasterKey *abe_key)
1010{
1011 struct TicketIssueHandle *ih = cls;
1012 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
1013 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
1014 struct GNUNET_GNSRECORD_Data code_record[1];
1015 struct GNUNET_ABE_AbeKey *rp_key;
1016 char *code_record_data;
1017 char **attrs;
1018 char *label;
1019 char *policy;
1020 int attrs_len;
1021 uint32_t i;
1022 size_t code_record_len;
1023
1024 //Create new ABE key for RP
1025 attrs_len = 0;
1026 for (le = ih->attrs->list_head; NULL != le; le = le->next)
1027 attrs_len++;
1028 attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1029 i = 0;
1030 for (le = ih->attrs->list_head; NULL != le; le = le->next) {
1031 GNUNET_asprintf (&policy, "%s_%lu",
1032 le->claim->name,
1033 le->claim->version);
1034 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1035 "Adding attribute to key: %s\n",
1036 policy);
1037 attrs[i] = policy;
1038 i++;
1039 }
1040 attrs[i] = NULL;
1041 rp_key = GNUNET_ABE_cpabe_create_key (abe_key,
1042 attrs);
1043
1044 //TODO review this wireformat
1045 code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
1046 ih->attrs,
1047 rp_key,
1048 &ecdhe_privkey,
1049 &code_record_data);
1050 code_record[0].data = code_record_data;
1051 code_record[0].data_size = code_record_len;
1052 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1053 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1054 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1055
1056 label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
1057 sizeof (uint64_t));
1058 //Publish record
1059 ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1060 &ih->identity,
1061 label,
1062 1,
1063 code_record,
1064 &store_ticket_issue_cont,
1065 ih);
1066 //for (; i > 0; i--)
1067 // GNUNET_free (attrs[i-1]);
1068 GNUNET_free (ecdhe_privkey);
1069 GNUNET_free (label);
1070 GNUNET_free (attrs);
1071 GNUNET_free (code_record_data);
1072 GNUNET_ABE_cpabe_delete_key (rp_key,
1073 GNUNET_YES);
1074 GNUNET_ABE_cpabe_delete_master_key (abe_key);
1075}
1076
1077
1078static int
1079check_issue_ticket_message(void *cls,
1080 const struct IssueTicketMessage *im)
1081{
1082 uint16_t size;
1083
1084 size = ntohs (im->header.size);
1085 if (size <= sizeof (struct IssueTicketMessage))
1086 {
1087 GNUNET_break (0);
1088 return GNUNET_SYSERR;
1089 }
1090 return GNUNET_OK;
1091}
1092
1093
1094static void
1095handle_issue_ticket_message (void *cls,
1096 const struct IssueTicketMessage *im)
1097{
1098 struct TicketIssueHandle *ih;
1099 struct IdpClient *idp = cls;
1100 size_t attrs_len;
1101
1102 ih = GNUNET_new (struct TicketIssueHandle);
1103 attrs_len = ntohs (im->attr_len);
1104 ih->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char*)&im[1], attrs_len);
1105 ih->r_id = ntohl (im->id);
1106 ih->client = idp;
1107 ih->identity = im->identity;
1108 GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
1109 &ih->ticket.identity);
1110 ih->ticket.audience = im->rp;
1111 ih->ticket.rnd =
1112 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1113 UINT64_MAX);
1114 GNUNET_CONTAINER_DLL_insert (idp->issue_op_head,
1115 idp->issue_op_tail,
1116 ih);
1117 bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
1118 GNUNET_SERVICE_client_continue (idp->client);
1119
1120}
1121
1122/**********************************************************
1123 * Revocation
1124 **********************************************************/
1125
1126/**
1127 * Cleanup revoke handle
1128 *
1129 * @param rh the ticket revocation handle
1130 */
1131static void
1132cleanup_revoke_ticket_handle (struct TicketRevocationHandle *rh)
1133{
1134 if (NULL != rh->attrs)
1135 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (rh->attrs);
1136 if (NULL != rh->rvk_attrs)
1137 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (rh->rvk_attrs);
1138 if (NULL != rh->abe_key)
1139 GNUNET_ABE_cpabe_delete_master_key (rh->abe_key);
1140 if (NULL != rh->ns_qe)
1141 GNUNET_NAMESTORE_cancel (rh->ns_qe);
1142 if (NULL != rh->ns_it)
1143 GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
1144 GNUNET_free (rh);
1145}
1146
1147
1148/**
1149 * Send revocation result
1150 *
1151 * @param rh ticket revocation handle
1152 * @param success GNUNET_OK if successful result
1153 */
1154static void
1155send_revocation_finished (struct TicketRevocationHandle *rh,
1156 uint32_t success)
1157{
1158 struct GNUNET_MQ_Envelope *env;
1159 struct RevokeTicketResultMessage *trm;
1160
1161 GNUNET_break(TKT_database->delete_ticket (TKT_database->cls,
1162 &rh->ticket));
1163
1164 env = GNUNET_MQ_msg (trm,
1165 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
1166 trm->id = htonl (rh->r_id);
1167 trm->success = htonl (success);
1168 GNUNET_MQ_send (rh->client->mq,
1169 env);
1170 GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head,
1171 rh->client->revoke_op_tail,
1172 rh);
1173}
1174
1175
1176/**
1177 * Process ticket from database
1178 *
1179 * @param cls struct TicketIterationProcResult
1180 * @param ticket the ticket
1181 * @param attrs the attributes
1182 */
1183static void
1184ticket_reissue_proc (void *cls,
1185 const struct GNUNET_RECLAIM_Ticket *ticket,
1186 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs);
1187
1188static void
1189revocation_reissue_tickets (struct TicketRevocationHandle *rh);
1190
1191
1192static void reissue_next (void *cls)
1193{
1194 struct TicketRevocationHandle *rh = cls;
1195 revocation_reissue_tickets (rh);
1196}
1197
1198
1199static void
1200reissue_ticket_cont (void *cls,
1201 int32_t success,
1202 const char *emsg)
1203{
1204 struct TicketRevocationHandle *rh = cls;
1205
1206 rh->ns_qe = NULL;
1207 if (GNUNET_SYSERR == success)
1208 {
1209 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1210 "Unknown Error\n");
1211 send_revocation_finished (rh, GNUNET_SYSERR);
1212 cleanup_revoke_ticket_handle (rh);
1213 return;
1214 }
1215 rh->offset++;
1216 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
1217}
1218
1219
1220/**
1221 * Process ticket from database
1222 *
1223 * @param cls struct TicketIterationProcResult
1224 * @param ticket the ticket
1225 * @param attrs the attributes
1226 */
1227static void
1228ticket_reissue_proc (void *cls,
1229 const struct GNUNET_RECLAIM_Ticket *ticket,
1230 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
1231{
1232 struct TicketRevocationHandle *rh = cls;
1233 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
1234 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le_rollover;
1235 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
1236 struct GNUNET_GNSRECORD_Data code_record[1];
1237 struct GNUNET_ABE_AbeKey *rp_key;
1238 char *code_record_data;
1239 char **attr_arr;
1240 char *label;
1241 char *policy;
1242 int attrs_len;
1243 uint32_t i;
1244 int reissue_ticket;
1245 size_t code_record_len;
1246
1247
1248 if (NULL == ticket)
1249 {
1250 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1251 "Iteration done\n");
1252 return;
1253 }
1254
1255 if (0 == memcmp (&ticket->audience,
1256 &rh->ticket.audience,
1257 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
1258 {
1259 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1260 "Do not reissue for this identity.!\n");
1261 label = GNUNET_STRINGS_data_to_string_alloc (&rh->ticket.rnd,
1262 sizeof (uint64_t));
1263 //Delete record
1264 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1265 &rh->identity,
1266 label,
1267 0,
1268 NULL,
1269 &reissue_ticket_cont,
1270 rh);
1271
1272 GNUNET_free (label);
1273 return;
1274 }
1275
1276 /*
1277 * Check if any attribute of this ticket intersects with a rollover attribute
1278 */
1279 reissue_ticket = GNUNET_NO;
1280 for (le = attrs->list_head; NULL != le; le = le->next)
1281 {
1282 for (le_rollover = rh->rvk_attrs->list_head;
1283 NULL != le_rollover;
1284 le_rollover = le_rollover->next)
1285 {
1286 if (0 == strcmp (le_rollover->claim->name,
1287 le->claim->name))
1288 {
1289 reissue_ticket = GNUNET_YES;
1290 le->claim->version = le_rollover->claim->version;
1291 }
1292 }
1293 }
1294
1295 if (GNUNET_NO == reissue_ticket)
1296 {
1297 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1298 "Skipping ticket.\n");
1299
1300 rh->offset++;
1301 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
1302
1303
1304 return;
1305 }
1306
1307 //Create new ABE key for RP
1308 attrs_len = 0;
1309
1310 /* If this is the RP we want to revoke attributes of, the do so */
1311
1312 for (le = attrs->list_head; NULL != le; le = le->next)
1313 attrs_len++;
1314 attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1315 i = 0;
1316 for (le = attrs->list_head; NULL != le; le = le->next) {
1317 GNUNET_asprintf (&policy, "%s_%lu",
1318 le->claim->name,
1319 le->claim->version);
1320 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1321 "Recreating key with %s\n", policy);
1322 attr_arr[i] = policy;
1323 i++;
1324 }
1325 attr_arr[i] = NULL;
1326 rp_key = GNUNET_ABE_cpabe_create_key (rh->abe_key,
1327 attr_arr);
1328
1329 //TODO review this wireformat
1330 code_record_len = serialize_abe_keyinfo2 (ticket,
1331 attrs,
1332 rp_key,
1333 &ecdhe_privkey,
1334 &code_record_data);
1335 code_record[0].data = code_record_data;
1336 code_record[0].data_size = code_record_len;
1337 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1338 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1339 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1340
1341 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
1342 sizeof (uint64_t));
1343 //Publish record
1344 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1345 &rh->identity,
1346 label,
1347 1,
1348 code_record,
1349 &reissue_ticket_cont,
1350 rh);
1351 //for (; i > 0; i--)
1352 // GNUNET_free (attr_arr[i-1]);
1353 GNUNET_free (ecdhe_privkey);
1354 GNUNET_free (label);
1355 GNUNET_free (attr_arr);
1356 GNUNET_free (code_record_data);
1357 GNUNET_ABE_cpabe_delete_key (rp_key, GNUNET_YES);
1358}
1359
1360
1361/* Prototype for below function */
1362static void
1363attr_reenc_cont (void *cls,
1364 int32_t success,
1365 const char *emsg);
1366
1367static void
1368revocation_reissue_tickets (struct TicketRevocationHandle *rh)
1369{
1370 int ret;
1371 /* Done, issue new keys */
1372 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1373 "Revocation Phase III: Reissuing Tickets\n");
1374 if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
1375 &rh->ticket.identity,
1376 GNUNET_NO,
1377 rh->offset,
1378 &ticket_reissue_proc,
1379 rh)))
1380 {
1381 GNUNET_break (0);
1382 }
1383 if (GNUNET_NO == ret)
1384 {
1385 send_revocation_finished (rh, GNUNET_OK);
1386 cleanup_revoke_ticket_handle (rh);
1387 return;
1388 }
1389}
1390
1391/**
1392 * Failed to check for attribute
1393 */
1394static void
1395check_attr_error (void *cls)
1396{
1397 struct TicketRevocationHandle *rh = cls;
1398 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1399 "Unable to check for existing attribute\n");
1400 rh->ns_qe = NULL;
1401 send_revocation_finished (rh, GNUNET_SYSERR);
1402 cleanup_revoke_ticket_handle (rh);
1403}
1404
1405
1406/**
1407 * Revoke next attribte by reencryption with
1408 * new ABE master
1409 */
1410static void
1411reenc_next_attribute (void *cls);
1412
1413/**
1414 * Check for existing attribute and overwrite
1415 */
1416static void
1417check_attr_cb (void *cls,
1418 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1419 const char *label,
1420 unsigned int rd_count,
1421 const struct GNUNET_GNSRECORD_Data *rd_old)
1422{
1423 struct TicketRevocationHandle *rh = cls;
1424 struct GNUNET_GNSRECORD_Data rd[1];
1425 char* buf;
1426 char* enc_buf;
1427 size_t enc_size;
1428 char* rd_buf;
1429 size_t buf_size;
1430 char* policy;
1431 uint32_t attr_ver;
1432
1433 rh->ns_qe = NULL;
1434 if (1 != rd_count) {
1435 GNUNET_SCHEDULER_add_now (&reenc_next_attribute,
1436 rh);
1437 return;
1438 }
1439
1440 buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim);
1441 buf = GNUNET_malloc (buf_size);
1442 rh->attrs->list_head->claim->version++;
1443 GNUNET_RECLAIM_ATTRIBUTE_serialize (rh->attrs->list_head->claim,
1444 buf);
1445 GNUNET_asprintf (&policy, "%s_%lu",
1446 rh->attrs->list_head->claim->name,
1447 rh->attrs->list_head->claim->version);
1448 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1449 "Encrypting with policy %s\n", policy);
1450 /**
1451 * Encrypt the attribute value and store in namestore
1452 */
1453 enc_size = GNUNET_ABE_cpabe_encrypt (buf,
1454 buf_size,
1455 policy, //Policy
1456 rh->abe_key,
1457 (void**)&enc_buf);
1458 GNUNET_free (buf);
1459 if (GNUNET_SYSERR == enc_size)
1460 {
1461 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1462 "Unable to re-encrypt with policy %s\n",
1463 policy);
1464 GNUNET_free (policy);
1465 send_revocation_finished (rh, GNUNET_SYSERR);
1466 cleanup_revoke_ticket_handle (rh);
1467 return;
1468 }
1469 GNUNET_free (policy);
1470
1471 rd[0].data_size = enc_size + sizeof (uint32_t);
1472 rd_buf = GNUNET_malloc (rd[0].data_size);
1473 attr_ver = htonl (rh->attrs->list_head->claim->version);
1474 GNUNET_memcpy (rd_buf,
1475 &attr_ver,
1476 sizeof (uint32_t));
1477 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1478 enc_buf,
1479 enc_size);
1480 rd[0].data = rd_buf;
1481 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1482 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1483 rd[0].expiration_time = rd_old[0].expiration_time;
1484 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1485 &rh->identity,
1486 rh->attrs->list_head->claim->name,
1487 1,
1488 rd,
1489 &attr_reenc_cont,
1490 rh);
1491 GNUNET_free (enc_buf);
1492 GNUNET_free (rd_buf);
1493}
1494
1495
1496/**
1497 * Revoke next attribte by reencryption with
1498 * new ABE master
1499 */
1500static void
1501reenc_next_attribute (void *cls)
1502{
1503 struct TicketRevocationHandle *rh = cls;
1504 if (NULL == rh->attrs->list_head)
1505 {
1506 revocation_reissue_tickets (rh);
1507 return;
1508 }
1509 /* First check if attribute still exists */
1510 rh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
1511 &rh->identity,
1512 rh->attrs->list_head->claim->name,
1513 &check_attr_error,
1514 rh,
1515 &check_attr_cb,
1516 rh);
1517}
1518
1519
1520/**
1521 * Namestore callback after revoked attribute
1522 * is stored
1523 */
1524static void
1525attr_reenc_cont (void *cls,
1526 int32_t success,
1527 const char *emsg)
1528{
1529 struct TicketRevocationHandle *rh = cls;
1530 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
1531
1532 rh->ns_qe = NULL;
1533 if (GNUNET_SYSERR == success)
1534 {
1535 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1536 "Failed to reencrypt attribute %s\n",
1537 emsg);
1538 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1539 return;
1540 }
1541 if (NULL == rh->attrs->list_head)
1542 {
1543 revocation_reissue_tickets (rh);
1544 return;
1545 }
1546 le = rh->attrs->list_head;
1547 GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1548 rh->attrs->list_tail,
1549 le);
1550 GNUNET_assert (NULL != rh->rvk_attrs);
1551 GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
1552 rh->rvk_attrs->list_tail,
1553 le);
1554
1555
1556 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1557 "Re-encrypting next attribute\n");
1558 reenc_next_attribute (rh);
1559}
1560
1561
1562static void
1563process_attributes_to_update (void *cls,
1564 const struct GNUNET_RECLAIM_Ticket *ticket,
1565 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
1566{
1567 struct TicketRevocationHandle *rh = cls;
1568
1569 rh->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (attrs);
1570 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1571 "Revocation Phase I: Collecting attributes\n");
1572 /* Reencrypt all attributes with new key */
1573 if (NULL == rh->attrs->list_head)
1574 {
1575 /* No attributes to reencrypt */
1576 send_revocation_finished (rh, GNUNET_OK);
1577 cleanup_revoke_ticket_handle (rh);
1578 return;
1579 } else {
1580 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1581 "Revocation Phase II: Re-encrypting attributes\n");
1582 reenc_next_attribute (rh);
1583 }
1584
1585}
1586
1587
1588
1589static void
1590get_ticket_after_abe_bootstrap (void *cls,
1591 struct GNUNET_ABE_AbeMasterKey *abe_key)
1592{
1593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1594 "Finished ABE bootstrap\n");
1595 struct TicketRevocationHandle *rh = cls;
1596 rh->abe_key = abe_key;
1597 TKT_database->get_ticket_attributes (TKT_database->cls,
1598 &rh->ticket,
1599 &process_attributes_to_update,
1600 rh);
1601}
1602
1603static int
1604check_revoke_ticket_message(void *cls,
1605 const struct RevokeTicketMessage *im)
1606{
1607 uint16_t size;
1608
1609 size = ntohs (im->header.size);
1610 if (size <= sizeof (struct RevokeTicketMessage))
1611 {
1612 GNUNET_break (0);
1613 return GNUNET_SYSERR;
1614 }
1615 return GNUNET_OK;
1616}
1617
1618static void
1619handle_revoke_ticket_message (void *cls,
1620 const struct RevokeTicketMessage *rm)
1621{
1622 struct TicketRevocationHandle *rh;
1623 struct IdpClient *idp = cls;
1624 struct GNUNET_RECLAIM_Ticket *ticket;
1625
1626 rh = GNUNET_new (struct TicketRevocationHandle);
1627 ticket = (struct GNUNET_RECLAIM_Ticket*)&rm[1];
1628 rh->rvk_attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
1629 rh->ticket = *ticket;
1630 rh->r_id = ntohl (rm->id);
1631 rh->client = idp;
1632 rh->identity = rm->identity;
1633 GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
1634 &rh->ticket.identity);
1635 GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head,
1636 idp->revoke_op_tail,
1637 rh);
1638 bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO);
1639 GNUNET_SERVICE_client_continue (idp->client);
1640
1641}
1642
1643/**
1644 * Cleanup ticket consume handle
1645 * @param handle the handle to clean up
1646 */
1647static void
1648cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
1649{
1650 struct ParallelLookup *lu;
1651 struct ParallelLookup *tmp;
1652 if (NULL != handle->lookup_request)
1653 GNUNET_GNS_lookup_cancel (handle->lookup_request);
1654 for (lu = handle->parallel_lookups_head;
1655 NULL != lu;) {
1656 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1657 GNUNET_free (lu->label);
1658 tmp = lu->next;
1659 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1660 handle->parallel_lookups_tail,
1661 lu);
1662 GNUNET_free (lu);
1663 lu = tmp;
1664 }
1665
1666 if (NULL != handle->key)
1667 GNUNET_ABE_cpabe_delete_key (handle->key,
1668 GNUNET_YES);
1669 if (NULL != handle->attrs)
1670 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (handle->attrs);
1671 GNUNET_free (handle);
1672}
1673
1674
1675
1676static int
1677check_consume_ticket_message(void *cls,
1678 const struct ConsumeTicketMessage *cm)
1679{
1680 uint16_t size;
1681
1682 size = ntohs (cm->header.size);
1683 if (size <= sizeof (struct ConsumeTicketMessage))
1684 {
1685 GNUNET_break (0);
1686 return GNUNET_SYSERR;
1687 }
1688 return GNUNET_OK;
1689}
1690
1691static void
1692process_parallel_lookup2 (void *cls, uint32_t rd_count,
1693 const struct GNUNET_GNSRECORD_Data *rd)
1694{
1695 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1696 "Parallel lookup finished (count=%u)\n", rd_count);
1697 struct ParallelLookup *parallel_lookup = cls;
1698 struct ConsumeTicketHandle *handle = parallel_lookup->handle;
1699 struct ConsumeTicketResultMessage *crm;
1700 struct GNUNET_MQ_Envelope *env;
1701 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *attr_le;
1702 struct GNUNET_TIME_Absolute decrypt_duration;
1703 char *data;
1704 char *data_tmp;
1705 ssize_t attr_len;
1706 size_t attrs_len;
1707
1708 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1709 handle->parallel_lookups_tail,
1710 parallel_lookup);
1711 GNUNET_free (parallel_lookup->label);
1712
1713 GNUNET_STATISTICS_update (stats,
1714 "attribute_lookup_time_total",
1715 GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us,
1716 GNUNET_YES);
1717 GNUNET_STATISTICS_update (stats,
1718 "attribute_lookups_count",
1719 1,
1720 GNUNET_YES);
1721
1722
1723 GNUNET_free (parallel_lookup);
1724 if (1 != rd_count)
1725 GNUNET_break(0);//TODO
1726 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1727 {
1728 decrypt_duration = GNUNET_TIME_absolute_get ();
1729 attr_len = GNUNET_ABE_cpabe_decrypt (rd->data + sizeof (uint32_t),
1730 rd->data_size - sizeof (uint32_t),
1731 handle->key,
1732 (void**)&data);
1733 if (GNUNET_SYSERR != attr_len)
1734 {
1735 GNUNET_STATISTICS_update (stats,
1736 "abe_decrypt_time_total",
1737 GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us,
1738 GNUNET_YES);
1739 GNUNET_STATISTICS_update (stats,
1740 "abe_decrypt_count",
1741 1,
1742 GNUNET_YES);
1743
1744 attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
1745 attr_le->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize (data,
1746 attr_len);
1747 attr_le->claim->version = ntohl(*(uint32_t*)rd->data);
1748 GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
1749 handle->attrs->list_tail,
1750 attr_le);
1751 GNUNET_free (data);
1752 }
1753 }
1754 if (NULL != handle->parallel_lookups_head)
1755 return; //Wait for more
1756 /* Else we are done */
1757
1758 /* Store ticket in DB */
1759 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1760 &handle->ticket,
1761 handle->attrs))
1762 {
1763 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1764 "Unable to store ticket after consume\n");
1765 GNUNET_break (0);
1766 }
1767
1768 GNUNET_SCHEDULER_cancel (handle->kill_task);
1769 attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (handle->attrs);
1770 env = GNUNET_MQ_msg_extra (crm,
1771 attrs_len,
1772 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
1773 crm->id = htonl (handle->r_id);
1774 crm->attrs_len = htons (attrs_len);
1775 crm->identity = handle->ticket.identity;
1776 data_tmp = (char *) &crm[1];
1777 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (handle->attrs,
1778 data_tmp);
1779 GNUNET_MQ_send (handle->client->mq, env);
1780 GNUNET_CONTAINER_DLL_remove (handle->client->consume_op_head,
1781 handle->client->consume_op_tail,
1782 handle);
1783 cleanup_consume_ticket_handle (handle);
1784}
1785
1786void
1787abort_parallel_lookups2 (void *cls)
1788{
1789 struct ConsumeTicketHandle *handle = cls;
1790 struct ParallelLookup *lu;
1791 struct ParallelLookup *tmp;
1792 struct AttributeResultMessage *arm;
1793 struct GNUNET_MQ_Envelope *env;
1794
1795 handle->kill_task = NULL;
1796 for (lu = handle->parallel_lookups_head;
1797 NULL != lu;) {
1798 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1799 GNUNET_free (lu->label);
1800 tmp = lu->next;
1801 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1802 handle->parallel_lookups_tail,
1803 lu);
1804 GNUNET_free (lu);
1805 lu = tmp;
1806 }
1807 env = GNUNET_MQ_msg (arm,
1808 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1809 arm->id = htonl (handle->r_id);
1810 arm->attr_len = htons (0);
1811 GNUNET_MQ_send (handle->client->mq, env);
1812
1813}
1814
1815
1816static void
1817process_consume_abe_key (void *cls, uint32_t rd_count,
1818 const struct GNUNET_GNSRECORD_Data *rd)
1819{
1820 struct ConsumeTicketHandle *handle = cls;
1821 struct GNUNET_HashCode new_key_hash;
1822 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1823 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1824 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1825 struct ParallelLookup *parallel_lookup;
1826 size_t size;
1827 char *buf;
1828 char *scope;
1829
1830 handle->lookup_request = NULL;
1831 if (1 != rd_count)
1832 {
1833 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1834 "Number of keys %d != 1.",
1835 rd_count);
1836 cleanup_consume_ticket_handle (handle);
1837 GNUNET_CONTAINER_DLL_remove (handle->client->consume_op_head,
1838 handle->client->consume_op_tail,
1839 handle);
1840 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1841 return;
1842 }
1843
1844 //Decrypt
1845 ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1846
1847 buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1848
1849 //Calculate symmetric key from ecdh parameters
1850 GNUNET_assert (GNUNET_OK ==
1851 GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
1852 ecdh_key,
1853 &new_key_hash));
1854 create_sym_key_from_ecdh (&new_key_hash,
1855 &enc_key,
1856 &enc_iv);
1857 size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1858 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1859 &enc_key,
1860 &enc_iv,
1861 buf);
1862
1863 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1864 "Decrypted bytes: %zd Expected bytes: %zd\n",
1865 size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1866 GNUNET_STATISTICS_update (stats,
1867 "abe_key_lookup_time_total",
1868 GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us,
1869 GNUNET_YES);
1870 GNUNET_STATISTICS_update (stats,
1871 "abe_key_lookups_count",
1872 1,
1873 GNUNET_YES);
1874 scopes = GNUNET_strdup (buf);
1875 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1876 "Scopes %s\n", scopes);
1877 handle->key = GNUNET_ABE_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1878 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1879 - strlen (scopes) - 1);
1880
1881 for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1882 {
1883 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1884 "Looking up %s\n", scope);
1885 parallel_lookup = GNUNET_new (struct ParallelLookup);
1886 parallel_lookup->handle = handle;
1887 parallel_lookup->label = GNUNET_strdup (scope);
1888 parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get();
1889 parallel_lookup->lookup_request
1890 = GNUNET_GNS_lookup (gns_handle,
1891 scope,
1892 &handle->ticket.identity,
1893 GNUNET_GNSRECORD_TYPE_ID_ATTR,
1894 GNUNET_GNS_LO_DEFAULT,
1895 &process_parallel_lookup2,
1896 parallel_lookup);
1897 GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1898 handle->parallel_lookups_tail,
1899 parallel_lookup);
1900 }
1901 GNUNET_free (scopes);
1902 GNUNET_free (buf);
1903 handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1904 &abort_parallel_lookups2,
1905 handle);
1906}
1907
1908
1909static void
1910handle_consume_ticket_message (void *cls,
1911 const struct ConsumeTicketMessage *cm)
1912{
1913 struct ConsumeTicketHandle *ch;
1914 struct IdpClient *idp = cls;
1915 char* rnd_label;
1916
1917 ch = GNUNET_new (struct ConsumeTicketHandle);
1918 ch->r_id = ntohl (cm->id);
1919 ch->client = idp;
1920 ch->identity = cm->identity;
1921 ch->attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
1922 GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
1923 &ch->identity_pub);
1924 ch->ticket = *((struct GNUNET_RECLAIM_Ticket*)&cm[1]);
1925 rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
1926 sizeof (uint64_t));
1927 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1928 "Looking for ABE key under %s\n", rnd_label);
1929 ch->lookup_start_time = GNUNET_TIME_absolute_get ();
1930 ch->lookup_request
1931 = GNUNET_GNS_lookup (gns_handle,
1932 rnd_label,
1933 &ch->ticket.identity,
1934 GNUNET_GNSRECORD_TYPE_ABE_KEY,
1935 GNUNET_GNS_LO_DEFAULT,
1936 &process_consume_abe_key,
1937 ch);
1938 GNUNET_CONTAINER_DLL_insert (idp->consume_op_head,
1939 idp->consume_op_tail,
1940 ch);
1941 GNUNET_free (rnd_label);
1942 GNUNET_SERVICE_client_continue (idp->client);
1943}
1944
1945/**
1946 * Cleanup attribute store handle
1947 *
1948 * @param handle handle to clean up
1949 */
1950static void
1951cleanup_as_handle (struct AttributeStoreHandle *handle)
1952{
1953 if (NULL != handle->ns_qe)
1954 GNUNET_NAMESTORE_cancel (handle->ns_qe);
1955 if (NULL != handle->claim)
1956 GNUNET_free (handle->claim);
1957 if (NULL != handle->abe_key)
1958 GNUNET_ABE_cpabe_delete_master_key (handle->abe_key);
1959 GNUNET_free (handle);
1960}
1961
1962static void
1963attr_store_cont (void *cls,
1964 int32_t success,
1965 const char *emsg)
1966{
1967 struct AttributeStoreHandle *as_handle = cls;
1968 struct GNUNET_MQ_Envelope *env;
1969 struct AttributeStoreResultMessage *acr_msg;
1970
1971 as_handle->ns_qe = NULL;
1972 GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head,
1973 as_handle->client->store_op_tail,
1974 as_handle);
1975
1976 if (GNUNET_SYSERR == success)
1977 {
1978 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1979 "Failed to store attribute %s\n",
1980 emsg);
1981 cleanup_as_handle (as_handle);
1982 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1983 return;
1984 }
1985
1986 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1987 "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1988 env = GNUNET_MQ_msg (acr_msg,
1989 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE_RESPONSE);
1990 acr_msg->id = htonl (as_handle->r_id);
1991 acr_msg->op_result = htonl (GNUNET_OK);
1992 GNUNET_MQ_send (as_handle->client->mq,
1993 env);
1994 cleanup_as_handle (as_handle);
1995}
1996
1997static void
1998attr_store_task (void *cls)
1999{
2000 struct AttributeStoreHandle *as_handle = cls;
2001 struct GNUNET_GNSRECORD_Data rd[1];
2002 char* buf;
2003 char* policy;
2004 char* enc_buf;
2005 char* rd_buf;
2006 size_t enc_size;
2007 size_t buf_size;
2008 uint32_t attr_ver;
2009
2010 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2011 "Storing attribute\n");
2012 buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (as_handle->claim);
2013 buf = GNUNET_malloc (buf_size);
2014
2015 GNUNET_RECLAIM_ATTRIBUTE_serialize (as_handle->claim,
2016 buf);
2017
2018 GNUNET_asprintf (&policy,
2019 "%s_%lu",
2020 as_handle->claim->name,
2021 as_handle->claim->version);
2022 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2023 "Encrypting with policy %s\n", policy);
2024 /**
2025 * Encrypt the attribute value and store in namestore
2026 */
2027 enc_size = GNUNET_ABE_cpabe_encrypt (buf,
2028 buf_size,
2029 policy, //Policy
2030 as_handle->abe_key,
2031 (void**)&enc_buf);
2032 if (GNUNET_SYSERR == enc_size)
2033 {
2034 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2035 "Failed to encrypt with policy %s\n",
2036 policy);
2037 GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head,
2038 as_handle->client->store_op_tail,
2039 as_handle);
2040
2041 cleanup_as_handle (as_handle);
2042 GNUNET_free (buf);
2043 GNUNET_free (policy);
2044 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
2045 return;
2046 }
2047 GNUNET_free (buf);
2048 GNUNET_free (policy);
2049 rd[0].data_size = enc_size + sizeof (uint32_t);
2050 rd_buf = GNUNET_malloc (rd[0].data_size);
2051 attr_ver = htonl (as_handle->claim->version);
2052 GNUNET_memcpy (rd_buf,
2053 &attr_ver,
2054 sizeof (uint32_t));
2055 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
2056 enc_buf,
2057 enc_size);
2058 rd[0].data = rd_buf;
2059 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
2060 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
2061 rd[0].expiration_time = as_handle->exp.rel_value_us;
2062 as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
2063 &as_handle->identity,
2064 as_handle->claim->name,
2065 1,
2066 rd,
2067 &attr_store_cont,
2068 as_handle);
2069 GNUNET_free (enc_buf);
2070 GNUNET_free (rd_buf);
2071}
2072
2073
2074static void
2075store_after_abe_bootstrap (void *cls,
2076 struct GNUNET_ABE_AbeMasterKey *abe_key)
2077{
2078 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2079 "Finished ABE bootstrap\n");
2080 struct AttributeStoreHandle *ash = cls;
2081 ash->abe_key = abe_key;
2082 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
2083}
2084
2085static int
2086check_attribute_store_message(void *cls,
2087 const struct AttributeStoreMessage *sam)
2088{
2089 uint16_t size;
2090
2091 size = ntohs (sam->header.size);
2092 if (size <= sizeof (struct AttributeStoreMessage))
2093 {
2094 GNUNET_break (0);
2095 return GNUNET_SYSERR;
2096 }
2097 return GNUNET_OK;
2098}
2099
2100
2101static void
2102handle_attribute_store_message (void *cls,
2103 const struct AttributeStoreMessage *sam)
2104{
2105 struct AttributeStoreHandle *as_handle;
2106 struct IdpClient *idp = cls;
2107 size_t data_len;
2108 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2109 "Received ATTRIBUTE_STORE message\n");
2110
2111 data_len = ntohs (sam->attr_len);
2112
2113 as_handle = GNUNET_new (struct AttributeStoreHandle);
2114 as_handle->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char*)&sam[1],
2115 data_len);
2116
2117 as_handle->r_id = ntohl (sam->id);
2118 as_handle->identity = sam->identity;
2119 as_handle->exp.rel_value_us = GNUNET_ntohll (sam->exp);
2120 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
2121 &as_handle->identity_pkey);
2122
2123 GNUNET_SERVICE_client_continue (idp->client);
2124 as_handle->client = idp;
2125 GNUNET_CONTAINER_DLL_insert (idp->store_op_head,
2126 idp->store_op_tail,
2127 as_handle);
2128 bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
2129}
2130
2131static void
2132cleanup_attribute_iter_handle (struct AttributeIterator *ai)
2133{
2134 if (NULL != ai->abe_key)
2135 GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
2136 GNUNET_free (ai);
2137}
2138
2139static void
2140attr_iter_error (void *cls)
2141{
2142 struct AttributeIterator *ai = cls;
2143 //TODO
2144 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2145 "Failed to iterate over attributes\n");
2146 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
2147 ai->client->attr_iter_tail,
2148 ai);
2149 cleanup_attribute_iter_handle (ai);
2150 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
2151}
2152
2153static void
2154attr_iter_finished (void *cls)
2155{
2156 struct AttributeIterator *ai = cls;
2157 struct GNUNET_MQ_Envelope *env;
2158 struct AttributeResultMessage *arm;
2159
2160 env = GNUNET_MQ_msg (arm,
2161 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
2162 arm->id = htonl (ai->request_id);
2163 arm->attr_len = htons (0);
2164 GNUNET_MQ_send (ai->client->mq, env);
2165 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
2166 ai->client->attr_iter_tail,
2167 ai);
2168 cleanup_attribute_iter_handle (ai);
2169}
2170
2171static void
2172attr_iter_cb (void *cls,
2173 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
2174 const char *label,
2175 unsigned int rd_count,
2176 const struct GNUNET_GNSRECORD_Data *rd)
2177{
2178 struct AttributeIterator *ai = cls;
2179 struct AttributeResultMessage *arm;
2180 struct GNUNET_ABE_AbeKey *key;
2181 struct GNUNET_MQ_Envelope *env;
2182 ssize_t msg_extra_len;
2183 char* attr_ser;
2184 char* attrs[2];
2185 char* data_tmp;
2186 char* policy;
2187 uint32_t attr_ver;
2188
2189 if (rd_count != 1)
2190 {
2191 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
2192 1);
2193 return;
2194 }
2195
2196 if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type)
2197 {
2198 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
2199 1);
2200 return;
2201 }
2202 attr_ver = ntohl(*((uint32_t*)rd->data));
2203 GNUNET_asprintf (&policy, "%s_%lu",
2204 label, attr_ver);
2205 attrs[0] = policy;
2206 attrs[1] = 0;
2207 key = GNUNET_ABE_cpabe_create_key (ai->abe_key,
2208 attrs);
2209 msg_extra_len = GNUNET_ABE_cpabe_decrypt (rd->data+sizeof (uint32_t),
2210 rd->data_size-sizeof (uint32_t),
2211 key,
2212 (void**)&attr_ser);
2213 if (GNUNET_SYSERR == msg_extra_len)
2214 {
2215 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
2216 1);
2217 return;
2218 }
2219
2220 GNUNET_ABE_cpabe_delete_key (key,
2221 GNUNET_YES);
2222 //GNUNET_free (policy);
2223 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2224 "Found attribute: %s\n", label);
2225 env = GNUNET_MQ_msg_extra (arm,
2226 msg_extra_len,
2227 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
2228 arm->id = htonl (ai->request_id);
2229 arm->attr_len = htons (msg_extra_len);
2230 GNUNET_CRYPTO_ecdsa_key_get_public (zone,
2231 &arm->identity);
2232 data_tmp = (char *) &arm[1];
2233 GNUNET_memcpy (data_tmp,
2234 attr_ser,
2235 msg_extra_len);
2236 GNUNET_MQ_send (ai->client->mq, env);
2237 GNUNET_free (attr_ser);
2238 GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
2239 ai->abe_key = NULL;
2240}
2241
2242
2243void
2244iterate_after_abe_bootstrap (void *cls,
2245 struct GNUNET_ABE_AbeMasterKey *abe_key)
2246{
2247 struct AttributeIterator *ai = cls;
2248 ai->abe_key = abe_key;
2249 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
2250 &ai->identity,
2251 &attr_iter_error,
2252 ai,
2253 &attr_iter_cb,
2254 ai,
2255 &attr_iter_finished,
2256 ai);
2257}
2258
2259
2260static void
2261iterate_next_after_abe_bootstrap (void *cls,
2262 struct GNUNET_ABE_AbeMasterKey *abe_key)
2263{
2264 struct AttributeIterator *ai = cls;
2265 ai->abe_key = abe_key;
2266 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
2267 1);
2268}
2269
2270
2271
2272static void
2273handle_iteration_start (void *cls,
2274 const struct AttributeIterationStartMessage *ais_msg)
2275{
2276 struct IdpClient *idp = cls;
2277 struct AttributeIterator *ai;
2278
2279 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2280 "Received ATTRIBUTE_ITERATION_START message\n");
2281 ai = GNUNET_new (struct AttributeIterator);
2282 ai->request_id = ntohl (ais_msg->id);
2283 ai->client = idp;
2284 ai->identity = ais_msg->identity;
2285
2286 GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head,
2287 idp->attr_iter_tail,
2288 ai);
2289 bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
2290 GNUNET_SERVICE_client_continue (idp->client);
2291}
2292
2293
2294static void
2295handle_iteration_stop (void *cls,
2296 const struct AttributeIterationStopMessage *ais_msg)
2297{
2298 struct IdpClient *idp = cls;
2299 struct AttributeIterator *ai;
2300 uint32_t rid;
2301
2302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2303 "Received `%s' message\n",
2304 "ATTRIBUTE_ITERATION_STOP");
2305 rid = ntohl (ais_msg->id);
2306 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
2307 if (ai->request_id == rid)
2308 break;
2309 if (NULL == ai)
2310 {
2311 GNUNET_break (0);
2312 GNUNET_SERVICE_client_drop (idp->client);
2313 return;
2314 }
2315 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head,
2316 idp->attr_iter_tail,
2317 ai);
2318 GNUNET_free (ai);
2319 GNUNET_SERVICE_client_continue (idp->client);
2320}
2321
2322
2323static void
2324handle_iteration_next (void *cls,
2325 const struct AttributeIterationNextMessage *ais_msg)
2326{
2327 struct IdpClient *idp = cls;
2328 struct AttributeIterator *ai;
2329 uint32_t rid;
2330
2331 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2332 "Received ATTRIBUTE_ITERATION_NEXT message\n");
2333 rid = ntohl (ais_msg->id);
2334 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
2335 if (ai->request_id == rid)
2336 break;
2337 if (NULL == ai)
2338 {
2339 GNUNET_break (0);
2340 GNUNET_SERVICE_client_drop (idp->client);
2341 return;
2342 }
2343 bootstrap_abe (&ai->identity,
2344 &iterate_next_after_abe_bootstrap,
2345 ai,
2346 GNUNET_NO);
2347 GNUNET_SERVICE_client_continue (idp->client);
2348}
2349
2350/**
2351 * Ticket iteration processor result
2352 */
2353enum ZoneIterationResult
2354{
2355 /**
2356 * Iteration start.
2357 */
2358 IT_START = 0,
2359
2360 /**
2361 * Found tickets,
2362 * Continue to iterate with next iteration_next call
2363 */
2364 IT_SUCCESS_MORE_AVAILABLE = 1,
2365
2366 /**
2367 * Iteration complete
2368 */
2369 IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
2370};
2371
2372
2373/**
2374 * Context for ticket iteration
2375 */
2376struct TicketIterationProcResult
2377{
2378 /**
2379 * The ticket iteration handle
2380 */
2381 struct TicketIteration *ti;
2382
2383 /**
2384 * Iteration result: iteration done?
2385 * #IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but
2386 * we got one for now and have sent it to the client
2387 * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
2388 * #IT_START: if we are still trying to find a result.
2389 */
2390 int res_iteration_finished;
2391
2392};
2393
2394static void
2395cleanup_ticket_iter_handle (struct TicketIteration *ti)
2396{
2397 GNUNET_free (ti);
2398}
2399
2400/**
2401 * Process ticket from database
2402 *
2403 * @param cls struct TicketIterationProcResult
2404 * @param ticket the ticket
2405 * @param attrs the attributes
2406 */
2407static void
2408ticket_iterate_proc (void *cls,
2409 const struct GNUNET_RECLAIM_Ticket *ticket,
2410 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
2411{
2412 struct TicketIterationProcResult *proc = cls;
2413
2414 if (NULL == ticket)
2415 {
2416 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2417 "Iteration done\n");
2418 proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2419 return;
2420 }
2421 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
2422 send_ticket_result (proc->ti->client,
2423 proc->ti->r_id,
2424 ticket,
2425 attrs);
2426
2427}
2428
2429/**
2430 * Perform ticket iteration step
2431 *
2432 * @param ti ticket iterator to process
2433 */
2434static void
2435run_ticket_iteration_round (struct TicketIteration *ti)
2436{
2437 struct TicketIterationProcResult proc;
2438 struct GNUNET_MQ_Envelope *env;
2439 struct TicketResultMessage *trm;
2440 int ret;
2441
2442 memset (&proc, 0, sizeof (proc));
2443 proc.ti = ti;
2444 proc.res_iteration_finished = IT_START;
2445 while (IT_START == proc.res_iteration_finished)
2446 {
2447 if (GNUNET_SYSERR ==
2448 (ret = TKT_database->iterate_tickets (TKT_database->cls,
2449 &ti->identity,
2450 ti->is_audience,
2451 ti->offset,
2452 &ticket_iterate_proc,
2453 &proc)))
2454 {
2455 GNUNET_break (0);
2456 break;
2457 }
2458 if (GNUNET_NO == ret)
2459 proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2460 ti->offset++;
2461 }
2462 if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
2463 {
2464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2465 "More results available\n");
2466 return; /* more later */
2467 }
2468 /* send empty response to indicate end of list */
2469 env = GNUNET_MQ_msg (trm,
2470 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
2471 trm->id = htonl (ti->r_id);
2472 GNUNET_MQ_send (ti->client->mq,
2473 env);
2474 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2475 ti->client->ticket_iter_tail,
2476 ti);
2477 cleanup_ticket_iter_handle (ti);
2478}
2479
2480static void
2481handle_ticket_iteration_start (void *cls,
2482 const struct TicketIterationStartMessage *tis_msg)
2483{
2484 struct IdpClient *client = cls;
2485 struct TicketIteration *ti;
2486
2487 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2488 "Received TICKET_ITERATION_START message\n");
2489 ti = GNUNET_new (struct TicketIteration);
2490 ti->r_id = ntohl (tis_msg->id);
2491 ti->offset = 0;
2492 ti->client = client;
2493 ti->identity = tis_msg->identity;
2494 ti->is_audience = ntohl (tis_msg->is_audience);
2495
2496 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2497 client->ticket_iter_tail,
2498 ti);
2499 run_ticket_iteration_round (ti);
2500 GNUNET_SERVICE_client_continue (client->client);
2501}
2502
2503
2504static void
2505handle_ticket_iteration_stop (void *cls,
2506 const struct TicketIterationStopMessage *tis_msg)
2507{
2508 struct IdpClient *client = cls;
2509 struct TicketIteration *ti;
2510 uint32_t rid;
2511
2512 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2513 "Received `%s' message\n",
2514 "TICKET_ITERATION_STOP");
2515 rid = ntohl (tis_msg->id);
2516 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2517 if (ti->r_id == rid)
2518 break;
2519 if (NULL == ti)
2520 {
2521 GNUNET_break (0);
2522 GNUNET_SERVICE_client_drop (client->client);
2523 return;
2524 }
2525 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2526 client->ticket_iter_tail,
2527 ti);
2528 cleanup_ticket_iter_handle (ti);
2529 GNUNET_SERVICE_client_continue (client->client);
2530}
2531
2532
2533static void
2534handle_ticket_iteration_next (void *cls,
2535 const struct TicketIterationNextMessage *tis_msg)
2536{
2537 struct IdpClient *client = cls;
2538 struct TicketIteration *ti;
2539 uint32_t rid;
2540
2541 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2542 "Received TICKET_ITERATION_NEXT message\n");
2543 rid = ntohl (tis_msg->id);
2544 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2545 if (ti->r_id == rid)
2546 break;
2547 if (NULL == ti)
2548 {
2549 GNUNET_break (0);
2550 GNUNET_SERVICE_client_drop (client->client);
2551 return;
2552 }
2553 run_ticket_iteration_round (ti);
2554 GNUNET_SERVICE_client_continue (client->client);
2555}
2556
2557
2558
2559
2560/**
2561 * Main function that will be run
2562 *
2563 * @param cls closure
2564 * @param c the configuration used
2565 * @param server the service handle
2566 */
2567static void
2568run (void *cls,
2569 const struct GNUNET_CONFIGURATION_Handle *c,
2570 struct GNUNET_SERVICE_Handle *server)
2571{
2572 char *database;
2573 cfg = c;
2574
2575 stats = GNUNET_STATISTICS_create ("reclaim", cfg);
2576
2577 //Connect to identity and namestore services
2578 ns_handle = GNUNET_NAMESTORE_connect (cfg);
2579 if (NULL == ns_handle)
2580 {
2581 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
2582 }
2583
2584 gns_handle = GNUNET_GNS_connect (cfg);
2585 if (NULL == gns_handle)
2586 {
2587 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
2588 }
2589 credential_handle = GNUNET_CREDENTIAL_connect (cfg);
2590 if (NULL == credential_handle)
2591 {
2592 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
2593 }
2594 identity_handle = GNUNET_IDENTITY_connect (cfg,
2595 NULL,
2596 NULL);
2597 /* Loading DB plugin */
2598 if (GNUNET_OK !=
2599 GNUNET_CONFIGURATION_get_value_string (cfg,
2600 "reclaim",
2601 "database",
2602 &database))
2603 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2604 "No database backend configured\n");
2605 GNUNET_asprintf (&db_lib_name,
2606 "libgnunet_plugin_reclaim_%s",
2607 database);
2608 TKT_database = GNUNET_PLUGIN_load (db_lib_name,
2609 (void *) cfg);
2610 GNUNET_free (database);
2611 if (NULL == TKT_database)
2612 {
2613 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2614 "Could not load database backend `%s'\n",
2615 db_lib_name);
2616 GNUNET_SCHEDULER_shutdown ();
2617 return;
2618 }
2619
2620 if (GNUNET_OK ==
2621 GNUNET_CONFIGURATION_get_value_time (cfg,
2622 "reclaim",
2623 "TOKEN_EXPIRATION_INTERVAL",
2624 &token_expiration_interval))
2625 {
2626 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2627 "Time window for zone iteration: %s\n",
2628 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
2629 GNUNET_YES));
2630 } else {
2631 token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
2632 }
2633
2634 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2635}
2636
2637/**
2638 * Called whenever a client is disconnected.
2639 *
2640 * @param cls closure
2641 * @param client identification of the client
2642 * @param app_ctx @a client
2643 */
2644static void
2645client_disconnect_cb (void *cls,
2646 struct GNUNET_SERVICE_Client *client,
2647 void *app_ctx)
2648{
2649 struct IdpClient *idp = app_ctx;
2650 struct AttributeIterator *ai;
2651 struct TicketIteration *ti;
2652 struct TicketRevocationHandle *rh;
2653 struct TicketIssueHandle *iss;
2654 struct ConsumeTicketHandle *ct;
2655 struct AttributeStoreHandle *as;
2656
2657 //TODO other operations
2658
2659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2660 "Client %p disconnected\n",
2661 client);
2662
2663 while (NULL != (iss = idp->issue_op_head))
2664 {
2665 GNUNET_CONTAINER_DLL_remove (idp->issue_op_head,
2666 idp->issue_op_tail,
2667 iss);
2668 cleanup_ticket_issue_handle (iss);
2669 }
2670 while (NULL != (ct = idp->consume_op_head))
2671 {
2672 GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
2673 idp->consume_op_tail,
2674 ct);
2675 cleanup_consume_ticket_handle (ct);
2676 }
2677 while (NULL != (as = idp->store_op_head))
2678 {
2679 GNUNET_CONTAINER_DLL_remove (idp->store_op_head,
2680 idp->store_op_tail,
2681 as);
2682 cleanup_as_handle (as);
2683 }
2684
2685 while (NULL != (ai = idp->attr_iter_head))
2686 {
2687 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head,
2688 idp->attr_iter_tail,
2689 ai);
2690 cleanup_attribute_iter_handle (ai);
2691 }
2692 while (NULL != (rh = idp->revoke_op_head))
2693 {
2694 GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head,
2695 idp->revoke_op_tail,
2696 rh);
2697 cleanup_revoke_ticket_handle (rh);
2698 }
2699 while (NULL != (ti = idp->ticket_iter_head))
2700 {
2701 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
2702 idp->ticket_iter_tail,
2703 ti);
2704 cleanup_ticket_iter_handle (ti);
2705 }
2706 GNUNET_free (idp);
2707}
2708
2709
2710/**
2711 * Add a client to our list of active clients.
2712 *
2713 * @param cls NULL
2714 * @param client client to add
2715 * @param mq message queue for @a client
2716 * @return internal namestore client structure for this client
2717 */
2718static void *
2719client_connect_cb (void *cls,
2720 struct GNUNET_SERVICE_Client *client,
2721 struct GNUNET_MQ_Handle *mq)
2722{
2723 struct IdpClient *idp;
2724 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2725 "Client %p connected\n",
2726 client);
2727 idp = GNUNET_new (struct IdpClient);
2728 idp->client = client;
2729 idp->mq = mq;
2730 return idp;
2731}
2732
2733
2734
2735/**
2736 * Define "main" method using service macro.
2737 */
2738GNUNET_SERVICE_MAIN
2739("reclaim",
2740 GNUNET_SERVICE_OPTION_NONE,
2741 &run,
2742 &client_connect_cb,
2743 &client_disconnect_cb,
2744 NULL,
2745 GNUNET_MQ_hd_var_size (attribute_store_message,
2746 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
2747 struct AttributeStoreMessage,
2748 NULL),
2749 GNUNET_MQ_hd_fixed_size (iteration_start,
2750 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
2751 struct AttributeIterationStartMessage,
2752 NULL),
2753 GNUNET_MQ_hd_fixed_size (iteration_next,
2754 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
2755 struct AttributeIterationNextMessage,
2756 NULL),
2757 GNUNET_MQ_hd_fixed_size (iteration_stop,
2758 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
2759 struct AttributeIterationStopMessage,
2760 NULL),
2761 GNUNET_MQ_hd_var_size (issue_ticket_message,
2762 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
2763 struct IssueTicketMessage,
2764 NULL),
2765 GNUNET_MQ_hd_var_size (consume_ticket_message,
2766 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
2767 struct ConsumeTicketMessage,
2768 NULL),
2769 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
2770 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
2771 struct TicketIterationStartMessage,
2772 NULL),
2773 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2774 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
2775 struct TicketIterationNextMessage,
2776 NULL),
2777 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2778 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
2779 struct TicketIterationStopMessage,
2780 NULL),
2781 GNUNET_MQ_hd_var_size (revoke_ticket_message,
2782 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
2783 struct RevokeTicketMessage,
2784 NULL),
2785 GNUNET_MQ_handler_end());
2786/* end of gnunet-service-reclaim.c */