diff options
Diffstat (limited to 'src/reclaim/gnunet-service-reclaim_tickets.c')
-rw-r--r-- | src/reclaim/gnunet-service-reclaim_tickets.c | 1894 |
1 files changed, 0 insertions, 1894 deletions
diff --git a/src/reclaim/gnunet-service-reclaim_tickets.c b/src/reclaim/gnunet-service-reclaim_tickets.c deleted file mode 100644 index 689fbc429..000000000 --- a/src/reclaim/gnunet-service-reclaim_tickets.c +++ /dev/null | |||
@@ -1,1894 +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 | /** | ||
22 | * @author Martin Schanzenbach | ||
23 | * @file src/reclaim/gnunet-service-reclaim_tickets.c | ||
24 | * @brief reclaim tickets | ||
25 | * | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include <inttypes.h> | ||
29 | #include "gnunet-service-reclaim_tickets.h" | ||
30 | |||
31 | |||
32 | /** | ||
33 | * FIXME: the default ticket iteration interval should probably | ||
34 | * be the minimim attribute expiration. | ||
35 | */ | ||
36 | #define DEFAULT_TICKET_REFRESH_INTERVAL GNUNET_TIME_UNIT_HOURS | ||
37 | |||
38 | /** | ||
39 | * Handle for a parallel GNS lookup job | ||
40 | * (Declaration further below) | ||
41 | */ | ||
42 | struct ParallelLookup; | ||
43 | |||
44 | |||
45 | /** | ||
46 | * A reference to a ticket stored in GNS | ||
47 | */ | ||
48 | struct TicketReference | ||
49 | { | ||
50 | /** | ||
51 | * DLL | ||
52 | */ | ||
53 | struct TicketReference *next; | ||
54 | |||
55 | /** | ||
56 | * DLL | ||
57 | */ | ||
58 | struct TicketReference *prev; | ||
59 | |||
60 | /** | ||
61 | * Attributes | ||
62 | */ | ||
63 | struct GNUNET_RECLAIM_AttributeList *attrs; | ||
64 | |||
65 | /** | ||
66 | * Tickets | ||
67 | */ | ||
68 | struct GNUNET_RECLAIM_Ticket ticket; | ||
69 | }; | ||
70 | |||
71 | |||
72 | /** | ||
73 | * Handle to a consume operation | ||
74 | */ | ||
75 | struct RECLAIM_TICKETS_ConsumeHandle | ||
76 | { | ||
77 | /** | ||
78 | * Ticket | ||
79 | */ | ||
80 | struct GNUNET_RECLAIM_Ticket ticket; | ||
81 | |||
82 | /** | ||
83 | * LookupRequest | ||
84 | */ | ||
85 | struct GNUNET_GNS_LookupRequest *lookup_request; | ||
86 | |||
87 | /** | ||
88 | * Audience Key | ||
89 | */ | ||
90 | struct GNUNET_CRYPTO_PrivateKey identity; | ||
91 | |||
92 | /** | ||
93 | * Audience Key | ||
94 | */ | ||
95 | struct GNUNET_CRYPTO_PublicKey identity_pub; | ||
96 | |||
97 | /** | ||
98 | * Lookup DLL | ||
99 | */ | ||
100 | struct ParallelLookup *parallel_lookups_head; | ||
101 | |||
102 | /** | ||
103 | * Lookup DLL | ||
104 | */ | ||
105 | struct ParallelLookup *parallel_lookups_tail; | ||
106 | |||
107 | /** | ||
108 | * Kill task | ||
109 | */ | ||
110 | struct GNUNET_SCHEDULER_Task *kill_task; | ||
111 | |||
112 | /** | ||
113 | * Attributes | ||
114 | */ | ||
115 | struct GNUNET_RECLAIM_AttributeList *attrs; | ||
116 | |||
117 | /** | ||
118 | * Presentations | ||
119 | */ | ||
120 | struct GNUNET_RECLAIM_PresentationList *presentations; | ||
121 | |||
122 | /** | ||
123 | * Lookup time | ||
124 | */ | ||
125 | struct GNUNET_TIME_Absolute lookup_start_time; | ||
126 | |||
127 | /** | ||
128 | * Callback | ||
129 | */ | ||
130 | RECLAIM_TICKETS_ConsumeCallback cb; | ||
131 | |||
132 | /** | ||
133 | * Callback closure | ||
134 | */ | ||
135 | void *cb_cls; | ||
136 | }; | ||
137 | |||
138 | |||
139 | /** | ||
140 | * Handle for a parallel GNS lookup job | ||
141 | */ | ||
142 | struct ParallelLookup | ||
143 | { | ||
144 | /* DLL */ | ||
145 | struct ParallelLookup *next; | ||
146 | |||
147 | /* DLL */ | ||
148 | struct ParallelLookup *prev; | ||
149 | |||
150 | /* The GNS request */ | ||
151 | struct GNUNET_GNS_LookupRequest *lookup_request; | ||
152 | |||
153 | /* The handle the return to */ | ||
154 | struct RECLAIM_TICKETS_ConsumeHandle *handle; | ||
155 | |||
156 | /** | ||
157 | * Lookup time | ||
158 | */ | ||
159 | struct GNUNET_TIME_Absolute lookup_start_time; | ||
160 | |||
161 | /* The label to look up */ | ||
162 | char *label; | ||
163 | }; | ||
164 | |||
165 | |||
166 | /** | ||
167 | * Ticket issue request handle | ||
168 | */ | ||
169 | struct TicketIssueHandle | ||
170 | { | ||
171 | /** | ||
172 | * Attributes to issue | ||
173 | */ | ||
174 | struct GNUNET_RECLAIM_AttributeList *attrs; | ||
175 | |||
176 | /** | ||
177 | * Presentations to add | ||
178 | */ | ||
179 | struct GNUNET_RECLAIM_PresentationList *presentations; | ||
180 | |||
181 | /** | ||
182 | * Issuer Key | ||
183 | */ | ||
184 | struct GNUNET_CRYPTO_PrivateKey identity; | ||
185 | |||
186 | /** | ||
187 | * Ticket to issue | ||
188 | */ | ||
189 | struct GNUNET_RECLAIM_Ticket ticket; | ||
190 | |||
191 | /** | ||
192 | * QueueEntry | ||
193 | */ | ||
194 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
195 | |||
196 | /** | ||
197 | * Namestore Iterator | ||
198 | */ | ||
199 | struct GNUNET_NAMESTORE_ZoneIterator *ns_it; | ||
200 | |||
201 | /** | ||
202 | * Callback | ||
203 | */ | ||
204 | RECLAIM_TICKETS_TicketResult cb; | ||
205 | |||
206 | /** | ||
207 | * Callback cls | ||
208 | */ | ||
209 | void *cb_cls; | ||
210 | }; | ||
211 | |||
212 | |||
213 | /** | ||
214 | * Ticket iterator | ||
215 | */ | ||
216 | struct RECLAIM_TICKETS_Iterator | ||
217 | { | ||
218 | /** | ||
219 | * Namestore queue entry | ||
220 | */ | ||
221 | struct GNUNET_NAMESTORE_ZoneIterator *ns_it; | ||
222 | |||
223 | /** | ||
224 | * Iter callback | ||
225 | */ | ||
226 | RECLAIM_TICKETS_TicketIter cb; | ||
227 | |||
228 | /** | ||
229 | * Iter cls | ||
230 | */ | ||
231 | void *cb_cls; | ||
232 | }; | ||
233 | |||
234 | |||
235 | struct RevokedAttributeEntry | ||
236 | { | ||
237 | /** | ||
238 | * DLL | ||
239 | */ | ||
240 | struct RevokedAttributeEntry *next; | ||
241 | |||
242 | /** | ||
243 | * DLL | ||
244 | */ | ||
245 | struct RevokedAttributeEntry *prev; | ||
246 | |||
247 | /** | ||
248 | * Old ID of the attribute | ||
249 | */ | ||
250 | struct GNUNET_RECLAIM_Identifier old_id; | ||
251 | |||
252 | /** | ||
253 | * New ID of the attribute | ||
254 | */ | ||
255 | struct GNUNET_RECLAIM_Identifier new_id; | ||
256 | }; | ||
257 | |||
258 | |||
259 | /** | ||
260 | * Ticket revocation request handle | ||
261 | */ | ||
262 | struct RECLAIM_TICKETS_RevokeHandle | ||
263 | { | ||
264 | /** | ||
265 | * Issuer Key | ||
266 | */ | ||
267 | struct GNUNET_CRYPTO_PrivateKey identity; | ||
268 | |||
269 | /** | ||
270 | * Callback | ||
271 | */ | ||
272 | RECLAIM_TICKETS_RevokeCallback cb; | ||
273 | |||
274 | /** | ||
275 | * Callback cls | ||
276 | */ | ||
277 | void *cb_cls; | ||
278 | |||
279 | /** | ||
280 | * Ticket to issue | ||
281 | */ | ||
282 | struct GNUNET_RECLAIM_Ticket ticket; | ||
283 | |||
284 | /** | ||
285 | * QueueEntry | ||
286 | */ | ||
287 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
288 | |||
289 | /** | ||
290 | * Namestore iterator | ||
291 | */ | ||
292 | struct GNUNET_NAMESTORE_ZoneIterator *ns_it; | ||
293 | |||
294 | /** | ||
295 | * Revoked attributes | ||
296 | */ | ||
297 | struct RevokedAttributeEntry *attrs_head; | ||
298 | |||
299 | /** | ||
300 | * Revoked attributes | ||
301 | */ | ||
302 | struct RevokedAttributeEntry *attrs_tail; | ||
303 | |||
304 | /** | ||
305 | * Current attribute to move | ||
306 | */ | ||
307 | struct RevokedAttributeEntry *move_attr; | ||
308 | |||
309 | /** | ||
310 | * Number of attributes in ticket | ||
311 | */ | ||
312 | unsigned int ticket_attrs; | ||
313 | |||
314 | /** | ||
315 | * Tickets to update | ||
316 | */ | ||
317 | struct TicketRecordsEntry *tickets_to_update_head; | ||
318 | |||
319 | /** | ||
320 | * Tickets to update | ||
321 | */ | ||
322 | struct TicketRecordsEntry *tickets_to_update_tail; | ||
323 | }; | ||
324 | |||
325 | |||
326 | /** | ||
327 | * Ticket expiration interval | ||
328 | */ | ||
329 | static struct GNUNET_TIME_Relative ticket_refresh_interval; | ||
330 | |||
331 | |||
332 | /* Namestore handle */ | ||
333 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
334 | |||
335 | |||
336 | /* GNS handle */ | ||
337 | static struct GNUNET_GNS_Handle *gns; | ||
338 | |||
339 | |||
340 | /* Handle to the statistics service */ | ||
341 | static struct GNUNET_STATISTICS_Handle *stats; | ||
342 | |||
343 | |||
344 | /** | ||
345 | * Cleanup revoke handle | ||
346 | * | ||
347 | * @param rh the ticket revocation handle | ||
348 | */ | ||
349 | static void | ||
350 | cleanup_rvk (struct RECLAIM_TICKETS_RevokeHandle *rh) | ||
351 | { | ||
352 | struct RevokedAttributeEntry *ae; | ||
353 | struct TicketRecordsEntry *le; | ||
354 | |||
355 | if (NULL != rh->ns_qe) | ||
356 | GNUNET_NAMESTORE_cancel (rh->ns_qe); | ||
357 | if (NULL != rh->ns_it) | ||
358 | GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it); | ||
359 | while (NULL != (ae = rh->attrs_head)) | ||
360 | { | ||
361 | GNUNET_CONTAINER_DLL_remove (rh->attrs_head, rh->attrs_tail, ae); | ||
362 | GNUNET_free (ae); | ||
363 | } | ||
364 | while (NULL != (le = rh->tickets_to_update_head)) | ||
365 | { | ||
366 | GNUNET_CONTAINER_DLL_remove (rh->tickets_to_update_head, | ||
367 | rh->tickets_to_update_head, | ||
368 | le); | ||
369 | if (NULL != le->data) | ||
370 | GNUNET_free (le->data); | ||
371 | if (NULL != le->label) | ||
372 | GNUNET_free (le->label); | ||
373 | GNUNET_free (le); | ||
374 | } | ||
375 | GNUNET_free (rh); | ||
376 | } | ||
377 | |||
378 | |||
379 | /** | ||
380 | * For each ticket, store new, updated attribute references | ||
381 | * (Implementation further below) | ||
382 | * | ||
383 | * @param cls handle to the operation | ||
384 | */ | ||
385 | static void | ||
386 | process_tickets (void *cls); | ||
387 | |||
388 | |||
389 | /** | ||
390 | * Finished storing updated attribute references. | ||
391 | * Abort on error, else continue processing tickets | ||
392 | * | ||
393 | * @param cls handle to the operation | ||
394 | * @param success result of namestore operation | ||
395 | * @param emsg (NULL on success) | ||
396 | */ | ||
397 | static void | ||
398 | ticket_processed (void *cls, enum GNUNET_ErrorCode ec) | ||
399 | { | ||
400 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
401 | |||
402 | rvk->ns_qe = NULL; | ||
403 | GNUNET_SCHEDULER_add_now (&process_tickets, rvk); | ||
404 | } | ||
405 | |||
406 | |||
407 | /** | ||
408 | * For each ticket, store new, updated attribute references | ||
409 | * | ||
410 | * @param cls handle to the operation | ||
411 | */ | ||
412 | static void | ||
413 | process_tickets (void *cls) | ||
414 | { | ||
415 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
416 | struct TicketRecordsEntry *le; | ||
417 | struct RevokedAttributeEntry *ae; | ||
418 | |||
419 | if (NULL == rvk->tickets_to_update_head) | ||
420 | { | ||
421 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
422 | "Finished updatding tickets, success\n"); | ||
423 | rvk->cb (rvk->cb_cls, GNUNET_OK); | ||
424 | cleanup_rvk (rvk); | ||
425 | return; | ||
426 | } | ||
427 | le = rvk->tickets_to_update_head; | ||
428 | GNUNET_CONTAINER_DLL_remove (rvk->tickets_to_update_head, | ||
429 | rvk->tickets_to_update_tail, | ||
430 | le); | ||
431 | struct GNUNET_GNSRECORD_Data rd[le->rd_count]; | ||
432 | if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (le->data_size, | ||
433 | le->data, | ||
434 | le->rd_count, | ||
435 | rd)) | ||
436 | { | ||
437 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
438 | "Unable to deserialize ticket record(s)\n"); | ||
439 | rvk->cb (rvk->cb_cls, GNUNET_SYSERR); | ||
440 | cleanup_rvk (rvk); | ||
441 | return; | ||
442 | } | ||
443 | for (int i = 0; i < le->rd_count; i++) | ||
444 | { | ||
445 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type) | ||
446 | continue; | ||
447 | for (ae = rvk->attrs_head; NULL != ae; ae = ae->next) | ||
448 | { | ||
449 | if (0 != memcmp (rd[i].data, &ae->old_id, sizeof(ae->old_id))) | ||
450 | continue; | ||
451 | rd[i].data = &ae->new_id; | ||
452 | } | ||
453 | } | ||
454 | rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh, | ||
455 | &rvk->identity, | ||
456 | le->label, | ||
457 | le->rd_count, | ||
458 | rd, | ||
459 | &ticket_processed, | ||
460 | rvk); | ||
461 | GNUNET_free (le->label); | ||
462 | GNUNET_free (le->data); | ||
463 | GNUNET_free (le); | ||
464 | } | ||
465 | |||
466 | |||
467 | /** | ||
468 | * Done collecting tickets. Start processing. | ||
469 | * | ||
470 | * @param cls handle to the operation | ||
471 | */ | ||
472 | static void | ||
473 | rvk_ticket_update_finished (void *cls) | ||
474 | { | ||
475 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
476 | |||
477 | rvk->ns_it = NULL; | ||
478 | GNUNET_SCHEDULER_add_now (&process_tickets, rvk); | ||
479 | } | ||
480 | |||
481 | |||
482 | /** | ||
483 | * We need to update all other tickets with the new attribute IDs. | ||
484 | * We first collect them all. Processing after. | ||
485 | * | ||
486 | * @param cls handle to the operation | ||
487 | * @param zone ticket issuer private key | ||
488 | * @param label ticket rnd | ||
489 | * @param rd_count size of record set | ||
490 | * @param rd record set | ||
491 | */ | ||
492 | static void | ||
493 | rvk_ticket_update (void *cls, | ||
494 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
495 | const char *label, | ||
496 | unsigned int rd_count, | ||
497 | const struct GNUNET_GNSRECORD_Data *rd) | ||
498 | { | ||
499 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
500 | struct TicketRecordsEntry *le; | ||
501 | struct RevokedAttributeEntry *ae; | ||
502 | int has_changed = GNUNET_NO; | ||
503 | |||
504 | /** Let everything point to the old record **/ | ||
505 | for (int i = 0; i < rd_count; i++) | ||
506 | { | ||
507 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type) | ||
508 | continue; | ||
509 | for (ae = rvk->attrs_head; NULL != ae; ae = ae->next) | ||
510 | { | ||
511 | if (0 != memcmp (rd[i].data, &ae->old_id, sizeof(ae->old_id))) | ||
512 | continue; | ||
513 | has_changed = GNUNET_YES; | ||
514 | break; | ||
515 | } | ||
516 | if (GNUNET_YES == has_changed) | ||
517 | break; | ||
518 | } | ||
519 | if (GNUNET_YES == has_changed) | ||
520 | { | ||
521 | le = GNUNET_new (struct TicketRecordsEntry); | ||
522 | le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | ||
523 | le->data = GNUNET_malloc (le->data_size); | ||
524 | le->rd_count = rd_count; | ||
525 | le->label = GNUNET_strdup (label); | ||
526 | GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data); | ||
527 | GNUNET_CONTAINER_DLL_insert (rvk->tickets_to_update_head, | ||
528 | rvk->tickets_to_update_tail, | ||
529 | le); | ||
530 | } | ||
531 | GNUNET_NAMESTORE_zone_iterator_next (rvk->ns_it, 1); | ||
532 | } | ||
533 | |||
534 | |||
535 | /** | ||
536 | * Error iterating namestore. Abort. | ||
537 | * | ||
538 | * @param cls handle to the operation | ||
539 | */ | ||
540 | static void | ||
541 | rvk_ns_iter_err (void *cls) | ||
542 | { | ||
543 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
544 | |||
545 | rvk->ns_it = NULL; | ||
546 | rvk->cb (rvk->cb_cls, GNUNET_SYSERR); | ||
547 | cleanup_rvk (rvk); | ||
548 | } | ||
549 | |||
550 | |||
551 | /** | ||
552 | * Error storing new attribute in namestore. Abort | ||
553 | * | ||
554 | * @param cls handle to the operation | ||
555 | */ | ||
556 | static void | ||
557 | rvk_ns_err (void *cls) | ||
558 | { | ||
559 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
560 | |||
561 | rvk->ns_qe = NULL; | ||
562 | rvk->cb (rvk->cb_cls, GNUNET_SYSERR); | ||
563 | cleanup_rvk (rvk); | ||
564 | } | ||
565 | |||
566 | |||
567 | /** | ||
568 | * We change every attribute ID of the ticket attributes we | ||
569 | * want to revoke. | ||
570 | * When we are done, we need to update any other ticket which | ||
571 | * included references to any of the changed attributes. | ||
572 | * | ||
573 | * @param rh handle to the operation | ||
574 | */ | ||
575 | static void | ||
576 | move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rh); | ||
577 | |||
578 | |||
579 | /** | ||
580 | * Delayed continuation for move_attrs | ||
581 | * | ||
582 | * @param cls handle to the operation. | ||
583 | */ | ||
584 | static void | ||
585 | move_attrs_cont (void *cls) | ||
586 | { | ||
587 | move_attrs ((struct RECLAIM_TICKETS_RevokeHandle *) cls); | ||
588 | } | ||
589 | |||
590 | |||
591 | /** | ||
592 | * Done deleting the old record. Abort on error. | ||
593 | * Else, continue updating attribute IDs. | ||
594 | * | ||
595 | * @param cls handle to the operation | ||
596 | * @param success result of the namestore operation | ||
597 | * @param emsg error message (NULL on success) | ||
598 | */ | ||
599 | static void | ||
600 | del_attr_finished (void *cls, enum GNUNET_ErrorCode ec) | ||
601 | { | ||
602 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
603 | |||
604 | rvk->ns_qe = NULL; | ||
605 | if (GNUNET_EC_NONE != ec) | ||
606 | { | ||
607 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
608 | "Error removing attribute: %s\n", | ||
609 | GNUNET_ErrorCode_get_hint (ec)); | ||
610 | rvk->cb (rvk->cb_cls, GNUNET_SYSERR); | ||
611 | cleanup_rvk (rvk); | ||
612 | return; | ||
613 | } | ||
614 | rvk->move_attr = rvk->move_attr->next; | ||
615 | GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk); | ||
616 | } | ||
617 | |||
618 | |||
619 | /** | ||
620 | * Updated an attribute ID. | ||
621 | * Abort on error if namestore operation failed. | ||
622 | * Else, we have to delete the old record. | ||
623 | * | ||
624 | * @param cls handle to the operation | ||
625 | * @param success result of the store operation | ||
626 | * @param emsg error message (NULL on success) | ||
627 | */ | ||
628 | static void | ||
629 | move_attr_finished (void *cls, enum GNUNET_ErrorCode ec) | ||
630 | { | ||
631 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
632 | char *label; | ||
633 | |||
634 | rvk->ns_qe = NULL; | ||
635 | if (GNUNET_EC_NONE != ec) | ||
636 | { | ||
637 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
638 | "Error moving attribute: %s\n", | ||
639 | GNUNET_ErrorCode_get_hint (ec)); | ||
640 | rvk->cb (rvk->cb_cls, GNUNET_SYSERR); | ||
641 | cleanup_rvk (rvk); | ||
642 | return; | ||
643 | } | ||
644 | label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id, | ||
645 | sizeof(rvk->move_attr->old_id)); | ||
646 | GNUNET_assert (NULL != label); | ||
647 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing attribute %s\n", label); | ||
648 | rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh, | ||
649 | &rvk->identity, | ||
650 | label, | ||
651 | 0, | ||
652 | NULL, | ||
653 | &del_attr_finished, | ||
654 | rvk); | ||
655 | GNUNET_free (label); | ||
656 | } | ||
657 | |||
658 | |||
659 | /** | ||
660 | * Got the referenced attribute. Updating the ID | ||
661 | * | ||
662 | * @param cls handle to the operation | ||
663 | * @param zone issuer identity | ||
664 | * @param label attribute ID | ||
665 | * @param rd_count size of record set (should be 1) | ||
666 | * @param rd record set (the attribute) | ||
667 | */ | ||
668 | static void | ||
669 | rvk_move_attr_cb (void *cls, | ||
670 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
671 | const char *label, | ||
672 | unsigned int rd_count, | ||
673 | const struct GNUNET_GNSRECORD_Data *rd) | ||
674 | { | ||
675 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
676 | struct GNUNET_GNSRECORD_Data new_rd[rd_count]; | ||
677 | struct RevokedAttributeEntry *le; | ||
678 | char *new_label; | ||
679 | char *attr_data; | ||
680 | |||
681 | rvk->ns_qe = NULL; | ||
682 | if (0 == rd_count) | ||
683 | { | ||
684 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
685 | "The claim %s no longer exists!\n", | ||
686 | label); | ||
687 | le = rvk->move_attr; | ||
688 | rvk->move_attr = le->next; | ||
689 | GNUNET_CONTAINER_DLL_remove (rvk->attrs_head, rvk->attrs_tail, le); | ||
690 | GNUNET_free (le); | ||
691 | GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk); | ||
692 | return; | ||
693 | } | ||
694 | GNUNET_RECLAIM_id_generate (&rvk->move_attr->new_id); | ||
695 | new_label = | ||
696 | GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id, | ||
697 | sizeof (rvk->move_attr->new_id)); | ||
698 | |||
699 | attr_data = NULL; | ||
700 | // new_rd = *rd; | ||
701 | for (int i = 0; i < rd_count; i++) | ||
702 | { | ||
703 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE == rd[i].record_type) | ||
704 | { | ||
705 | /** find a new place for this attribute **/ | ||
706 | struct GNUNET_RECLAIM_Attribute *claim; | ||
707 | GNUNET_RECLAIM_attribute_deserialize (rd[i].data, | ||
708 | rd[i].data_size, | ||
709 | &claim); | ||
710 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
711 | "Attribute to update: Name=%s\n", | ||
712 | claim->name); | ||
713 | claim->id = rvk->move_attr->new_id; | ||
714 | new_rd[i].data_size = GNUNET_RECLAIM_attribute_serialize_get_size (claim); | ||
715 | attr_data = GNUNET_malloc (rd[i].data_size); | ||
716 | new_rd[i].data_size = GNUNET_RECLAIM_attribute_serialize (claim, | ||
717 | attr_data); | ||
718 | new_rd[i].data = attr_data; | ||
719 | new_rd[i].record_type = rd[i].record_type; | ||
720 | new_rd[i].flags = rd[i].flags; | ||
721 | new_rd[i].expiration_time = rd[i].expiration_time; | ||
722 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label); | ||
723 | GNUNET_free (claim); | ||
724 | } | ||
725 | else if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type) | ||
726 | { | ||
727 | struct GNUNET_RECLAIM_Credential *credential; | ||
728 | credential = GNUNET_RECLAIM_credential_deserialize (rd[i].data, | ||
729 | rd[i].data_size); | ||
730 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
731 | "Credential to update: Name=%s\n", | ||
732 | credential->name); | ||
733 | credential->id = rvk->move_attr->new_id; | ||
734 | new_rd[i].data_size = | ||
735 | GNUNET_RECLAIM_credential_serialize_get_size (credential); | ||
736 | attr_data = GNUNET_malloc (rd[i].data_size); | ||
737 | new_rd[i].data_size = GNUNET_RECLAIM_credential_serialize (credential, | ||
738 | attr_data); | ||
739 | new_rd[i].data = attr_data; | ||
740 | new_rd[i].record_type = rd[i].record_type; | ||
741 | new_rd[i].flags = rd[i].flags; | ||
742 | new_rd[i].expiration_time = rd[i].expiration_time; | ||
743 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential %s\n", | ||
744 | new_label); | ||
745 | GNUNET_free (credential); | ||
746 | } | ||
747 | else { | ||
748 | memcpy (&new_rd[i], &rd[i], sizeof (struct GNUNET_GNSRECORD_Data)); | ||
749 | } | ||
750 | } | ||
751 | rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh, | ||
752 | &rvk->identity, | ||
753 | new_label, | ||
754 | rd_count, | ||
755 | new_rd, | ||
756 | &move_attr_finished, | ||
757 | rvk); | ||
758 | GNUNET_free (new_label); | ||
759 | GNUNET_free (attr_data); | ||
760 | } | ||
761 | |||
762 | |||
763 | static void | ||
764 | move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rvk) | ||
765 | { | ||
766 | char *label; | ||
767 | |||
768 | if (NULL == rvk->move_attr) | ||
769 | { | ||
770 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished moving attributes\n"); | ||
771 | rvk->ns_it = | ||
772 | GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
773 | &rvk->identity, | ||
774 | &rvk_ns_iter_err, | ||
775 | rvk, | ||
776 | &rvk_ticket_update, | ||
777 | rvk, | ||
778 | &rvk_ticket_update_finished, | ||
779 | rvk); | ||
780 | return; | ||
781 | } | ||
782 | label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id, | ||
783 | sizeof (rvk->move_attr->old_id)); | ||
784 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Moving claim %s\n", label); | ||
785 | |||
786 | rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh, | ||
787 | &rvk->identity, | ||
788 | label, | ||
789 | &rvk_ns_err, | ||
790 | rvk, | ||
791 | &rvk_move_attr_cb, | ||
792 | rvk); | ||
793 | GNUNET_free (label); | ||
794 | } | ||
795 | |||
796 | |||
797 | /** | ||
798 | * Finished deleting ticket and attribute references. | ||
799 | * Abort on failure. | ||
800 | * Else, we start changing every attribute ID in the | ||
801 | * found attribute references so that access is no longer | ||
802 | * possible. | ||
803 | * | ||
804 | * @param cls handle to the operation | ||
805 | * @param success Namestore operation return value | ||
806 | * @param emsg error message (NULL on success) | ||
807 | */ | ||
808 | static void | ||
809 | remove_ticket_cont (void *cls, enum GNUNET_ErrorCode ec) | ||
810 | { | ||
811 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
812 | |||
813 | rvk->ns_qe = NULL; | ||
814 | if (GNUNET_EC_NONE != ec) | ||
815 | { | ||
816 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", | ||
817 | GNUNET_ErrorCode_get_hint (ec)); | ||
818 | rvk->cb (rvk->cb_cls, GNUNET_SYSERR); | ||
819 | cleanup_rvk (rvk); | ||
820 | return; | ||
821 | } | ||
822 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted ticket\n"); | ||
823 | if (0 == rvk->ticket_attrs) | ||
824 | { | ||
825 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
826 | "No attributes to move... strange\n"); | ||
827 | rvk->cb (rvk->cb_cls, GNUNET_OK); | ||
828 | cleanup_rvk (rvk); | ||
829 | return; | ||
830 | } | ||
831 | rvk->move_attr = rvk->attrs_head; | ||
832 | move_attrs (rvk); | ||
833 | } | ||
834 | |||
835 | |||
836 | /** | ||
837 | * We found the attribute references. | ||
838 | * Store them for later and remove the record set. | ||
839 | * | ||
840 | * @param cls handle to the operation | ||
841 | * @param zone the issuer key | ||
842 | * @param label ticket rnd | ||
843 | * @param rd_count size of record set | ||
844 | * @param rd record set | ||
845 | */ | ||
846 | static void | ||
847 | revoke_attrs_cb (void *cls, | ||
848 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
849 | const char *label, | ||
850 | unsigned int rd_count, | ||
851 | const struct GNUNET_GNSRECORD_Data *rd) | ||
852 | |||
853 | { | ||
854 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
855 | struct RevokedAttributeEntry *le; | ||
856 | |||
857 | rvk->ns_qe = NULL; | ||
858 | /** | ||
859 | * Temporarily store attribute references. | ||
860 | * We need it later. | ||
861 | */ | ||
862 | for (int i = 0; i < rd_count; i++) | ||
863 | { | ||
864 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type) | ||
865 | continue; | ||
866 | le = GNUNET_new (struct RevokedAttributeEntry); | ||
867 | le->old_id = *((struct GNUNET_RECLAIM_Identifier *) rd[i].data); | ||
868 | GNUNET_CONTAINER_DLL_insert (rvk->attrs_head, rvk->attrs_tail, le); | ||
869 | rvk->ticket_attrs++; | ||
870 | } | ||
871 | |||
872 | /** Remove attribute references **/ | ||
873 | rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh, | ||
874 | &rvk->identity, | ||
875 | label, | ||
876 | 0, | ||
877 | NULL, | ||
878 | &remove_ticket_cont, | ||
879 | rvk); | ||
880 | } | ||
881 | |||
882 | |||
883 | /** | ||
884 | * Failed to query namestore. Abort operation | ||
885 | * | ||
886 | * @param cls handle to the operation | ||
887 | */ | ||
888 | static void | ||
889 | rvk_attrs_err_cb (void *cls) | ||
890 | { | ||
891 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
892 | |||
893 | rvk->cb (rvk->cb_cls, GNUNET_SYSERR); | ||
894 | cleanup_rvk (rvk); | ||
895 | } | ||
896 | |||
897 | |||
898 | /** | ||
899 | * Revoke a ticket. | ||
900 | * We start by looking up attribute references in order | ||
901 | * to change attribute IDs. | ||
902 | * | ||
903 | * @param ticket ticket to revoke | ||
904 | * @param identity private key of issuer | ||
905 | * @param cb revocation status callback | ||
906 | * @param cb_cls callback closure | ||
907 | * @return handle to the operation | ||
908 | */ | ||
909 | struct RECLAIM_TICKETS_RevokeHandle * | ||
910 | RECLAIM_TICKETS_revoke (const struct GNUNET_RECLAIM_Ticket *ticket, | ||
911 | const struct GNUNET_CRYPTO_PrivateKey *identity, | ||
912 | RECLAIM_TICKETS_RevokeCallback cb, | ||
913 | void *cb_cls) | ||
914 | { | ||
915 | struct RECLAIM_TICKETS_RevokeHandle *rvk; | ||
916 | char *label; | ||
917 | |||
918 | rvk = GNUNET_new (struct RECLAIM_TICKETS_RevokeHandle); | ||
919 | rvk->cb = cb; | ||
920 | rvk->cb_cls = cb_cls; | ||
921 | rvk->identity = *identity; | ||
922 | rvk->ticket = *ticket; | ||
923 | GNUNET_CRYPTO_key_get_public (&rvk->identity, &rvk->ticket.identity); | ||
924 | /** Get shared attributes **/ | ||
925 | label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, | ||
926 | sizeof(ticket->rnd)); | ||
927 | GNUNET_assert (NULL != label); | ||
928 | rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh, | ||
929 | identity, | ||
930 | label, | ||
931 | &rvk_attrs_err_cb, | ||
932 | rvk, | ||
933 | &revoke_attrs_cb, | ||
934 | rvk); | ||
935 | GNUNET_free (label); | ||
936 | return rvk; | ||
937 | } | ||
938 | |||
939 | |||
940 | /** | ||
941 | * Cancel a revocation. | ||
942 | * | ||
943 | * @param rh handle to the operation | ||
944 | */ | ||
945 | void | ||
946 | RECLAIM_TICKETS_revoke_cancel (struct RECLAIM_TICKETS_RevokeHandle *rh) | ||
947 | { | ||
948 | GNUNET_assert (NULL != rh); | ||
949 | cleanup_rvk (rh); | ||
950 | } | ||
951 | |||
952 | |||
953 | /******************************* | ||
954 | * Ticket consume | ||
955 | *******************************/ | ||
956 | |||
957 | /** | ||
958 | * Cleanup ticket consume handle | ||
959 | * | ||
960 | * @param cth the handle to clean up | ||
961 | */ | ||
962 | static void | ||
963 | cleanup_cth (struct RECLAIM_TICKETS_ConsumeHandle *cth) | ||
964 | { | ||
965 | struct ParallelLookup *lu; | ||
966 | |||
967 | if (NULL != cth->lookup_request) | ||
968 | GNUNET_GNS_lookup_cancel (cth->lookup_request); | ||
969 | if (NULL != cth->kill_task) | ||
970 | GNUNET_SCHEDULER_cancel (cth->kill_task); | ||
971 | while (NULL != (lu = cth->parallel_lookups_head)) | ||
972 | { | ||
973 | if (NULL != lu->lookup_request) | ||
974 | GNUNET_GNS_lookup_cancel (lu->lookup_request); | ||
975 | GNUNET_free (lu->label); | ||
976 | GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head, | ||
977 | cth->parallel_lookups_tail, | ||
978 | lu); | ||
979 | GNUNET_free (lu); | ||
980 | } | ||
981 | |||
982 | if (NULL != cth->attrs) | ||
983 | GNUNET_RECLAIM_attribute_list_destroy (cth->attrs); | ||
984 | if (NULL != cth->presentations) | ||
985 | GNUNET_RECLAIM_presentation_list_destroy (cth->presentations); | ||
986 | GNUNET_free (cth); | ||
987 | } | ||
988 | |||
989 | |||
990 | /** | ||
991 | * We found an attribute record. | ||
992 | * | ||
993 | * @param cls handle to the operation | ||
994 | * @param rd_count size of record set | ||
995 | * @param rd record set | ||
996 | */ | ||
997 | static void | ||
998 | process_parallel_lookup_result (void *cls, | ||
999 | uint32_t rd_count, | ||
1000 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1001 | { | ||
1002 | struct ParallelLookup *parallel_lookup = cls; | ||
1003 | struct RECLAIM_TICKETS_ConsumeHandle *cth = parallel_lookup->handle; | ||
1004 | struct GNUNET_RECLAIM_AttributeListEntry *attr_le; | ||
1005 | |||
1006 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1007 | "Parallel lookup finished (count=%u)\n", | ||
1008 | rd_count); | ||
1009 | |||
1010 | GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head, | ||
1011 | cth->parallel_lookups_tail, | ||
1012 | parallel_lookup); | ||
1013 | GNUNET_free (parallel_lookup->label); | ||
1014 | |||
1015 | GNUNET_STATISTICS_update (stats, | ||
1016 | "attribute_lookup_time_total", | ||
1017 | GNUNET_TIME_absolute_get_duration ( | ||
1018 | parallel_lookup->lookup_start_time) | ||
1019 | .rel_value_us, | ||
1020 | GNUNET_YES); | ||
1021 | GNUNET_STATISTICS_update (stats, "attribute_lookups_count", 1, GNUNET_YES); | ||
1022 | |||
1023 | |||
1024 | GNUNET_free (parallel_lookup); | ||
1025 | if (0 == rd_count) | ||
1026 | GNUNET_break (0); | ||
1027 | // REMARK: It is possible now to find rd_count > 1 | ||
1028 | for (int i = 0; i < rd_count; i++) | ||
1029 | { | ||
1030 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd[i].record_type) | ||
1031 | continue; | ||
1032 | attr_le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); | ||
1033 | GNUNET_RECLAIM_attribute_deserialize (rd[i].data, rd[i].data_size, | ||
1034 | &attr_le->attribute); | ||
1035 | GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head, | ||
1036 | cth->attrs->list_tail, | ||
1037 | attr_le); | ||
1038 | } | ||
1039 | if (NULL != cth->parallel_lookups_head) | ||
1040 | return; // Wait for more | ||
1041 | /* Else we are done */ | ||
1042 | cth->cb (cth->cb_cls, &cth->ticket.identity, | ||
1043 | cth->attrs, cth->presentations, GNUNET_OK, NULL); | ||
1044 | cleanup_cth (cth); | ||
1045 | } | ||
1046 | |||
1047 | |||
1048 | /** | ||
1049 | * Cancel the lookups for attribute records | ||
1050 | * | ||
1051 | * @param cls handle to the operation | ||
1052 | */ | ||
1053 | static void | ||
1054 | abort_parallel_lookups (void *cls) | ||
1055 | { | ||
1056 | struct RECLAIM_TICKETS_ConsumeHandle *cth = cls; | ||
1057 | struct ParallelLookup *lu; | ||
1058 | struct ParallelLookup *tmp; | ||
1059 | |||
1060 | cth->kill_task = NULL; | ||
1061 | for (lu = cth->parallel_lookups_head; NULL != lu;) | ||
1062 | { | ||
1063 | GNUNET_GNS_lookup_cancel (lu->lookup_request); | ||
1064 | GNUNET_free (lu->label); | ||
1065 | tmp = lu->next; | ||
1066 | GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head, | ||
1067 | cth->parallel_lookups_tail, | ||
1068 | lu); | ||
1069 | GNUNET_free (lu); | ||
1070 | lu = tmp; | ||
1071 | } | ||
1072 | cth->cb (cth->cb_cls, NULL, NULL, NULL, GNUNET_SYSERR, "Aborted"); | ||
1073 | } | ||
1074 | |||
1075 | |||
1076 | /** | ||
1077 | * GNS result with attribute references. | ||
1078 | * For each result, we start a (parallel) lookup of the actual | ||
1079 | * attribute record under the referenced label. | ||
1080 | * | ||
1081 | * @param cls handle to the operation | ||
1082 | * @param rd_count size of the record set | ||
1083 | * @param rd record set | ||
1084 | */ | ||
1085 | static void | ||
1086 | lookup_authz_cb (void *cls, | ||
1087 | uint32_t rd_count, | ||
1088 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1089 | { | ||
1090 | struct RECLAIM_TICKETS_ConsumeHandle *cth = cls; | ||
1091 | struct ParallelLookup *parallel_lookup; | ||
1092 | char *lbl; | ||
1093 | struct GNUNET_RECLAIM_PresentationListEntry *ale; | ||
1094 | |||
1095 | cth->lookup_request = NULL; | ||
1096 | |||
1097 | GNUNET_STATISTICS_update (stats, | ||
1098 | "reclaim_authz_lookup_time_total", | ||
1099 | GNUNET_TIME_absolute_get_duration ( | ||
1100 | cth->lookup_start_time) | ||
1101 | .rel_value_us, | ||
1102 | GNUNET_YES); | ||
1103 | GNUNET_STATISTICS_update (stats, | ||
1104 | "reclaim_authz_lookups_count", | ||
1105 | 1, | ||
1106 | GNUNET_YES); | ||
1107 | |||
1108 | for (int i = 0; i < rd_count; i++) | ||
1109 | { | ||
1110 | /** | ||
1111 | * Check if record is a credential presentation or an attribute | ||
1112 | * reference. | ||
1113 | */ | ||
1114 | switch (rd[i].record_type) | ||
1115 | { | ||
1116 | case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION: | ||
1117 | ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry); | ||
1118 | ale->presentation = | ||
1119 | GNUNET_RECLAIM_presentation_deserialize (rd[i].data, | ||
1120 | rd[i].data_size); | ||
1121 | GNUNET_CONTAINER_DLL_insert (cth->presentations->list_head, | ||
1122 | cth->presentations->list_tail, | ||
1123 | ale); | ||
1124 | break; | ||
1125 | case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF: | ||
1126 | lbl = GNUNET_STRINGS_data_to_string_alloc (rd[i].data, rd[i].data_size); | ||
1127 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ticket reference found %s\n", lbl); | ||
1128 | parallel_lookup = GNUNET_new (struct ParallelLookup); | ||
1129 | parallel_lookup->handle = cth; | ||
1130 | parallel_lookup->label = lbl; | ||
1131 | parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get (); | ||
1132 | parallel_lookup->lookup_request = | ||
1133 | GNUNET_GNS_lookup (gns, | ||
1134 | lbl, | ||
1135 | &cth->ticket.identity, | ||
1136 | GNUNET_GNSRECORD_TYPE_ANY, | ||
1137 | GNUNET_GNS_LO_DEFAULT, | ||
1138 | &process_parallel_lookup_result, | ||
1139 | parallel_lookup); | ||
1140 | GNUNET_CONTAINER_DLL_insert (cth->parallel_lookups_head, | ||
1141 | cth->parallel_lookups_tail, | ||
1142 | parallel_lookup); | ||
1143 | break; | ||
1144 | default: | ||
1145 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1146 | "Ignoring unknown record type %d", rd[i].record_type); | ||
1147 | } | ||
1148 | } | ||
1149 | /** | ||
1150 | * We started lookups. Add a timeout task. | ||
1151 | * FIXME: Really needed here? | ||
1152 | */ | ||
1153 | if (NULL != cth->parallel_lookups_head) | ||
1154 | { | ||
1155 | cth->kill_task = GNUNET_SCHEDULER_add_delayed ( | ||
1156 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3), | ||
1157 | &abort_parallel_lookups, | ||
1158 | cth); | ||
1159 | return; | ||
1160 | } | ||
1161 | /** | ||
1162 | * No references found, return empty attribute list | ||
1163 | */ | ||
1164 | cth->cb (cth->cb_cls, &cth->ticket.identity, | ||
1165 | cth->attrs, NULL, GNUNET_OK, NULL); | ||
1166 | cleanup_cth (cth); | ||
1167 | } | ||
1168 | |||
1169 | |||
1170 | /** | ||
1171 | * Consume a ticket. | ||
1172 | * We first looking attribute references under the label | ||
1173 | * ticket.rnd in GNS. | ||
1174 | * | ||
1175 | * @param id the audience of the ticket | ||
1176 | * @param ticket the ticket to consume | ||
1177 | * @param cb callback to call with attributes of ticket | ||
1178 | * @param cb_cls callback closure | ||
1179 | * @return handle to the operation | ||
1180 | */ | ||
1181 | struct RECLAIM_TICKETS_ConsumeHandle * | ||
1182 | RECLAIM_TICKETS_consume (const struct GNUNET_CRYPTO_PrivateKey *id, | ||
1183 | const struct GNUNET_RECLAIM_Ticket *ticket, | ||
1184 | RECLAIM_TICKETS_ConsumeCallback cb, | ||
1185 | void *cb_cls) | ||
1186 | { | ||
1187 | struct RECLAIM_TICKETS_ConsumeHandle *cth; | ||
1188 | char *label; | ||
1189 | |||
1190 | cth = GNUNET_new (struct RECLAIM_TICKETS_ConsumeHandle); | ||
1191 | |||
1192 | cth->identity = *id; | ||
1193 | GNUNET_CRYPTO_key_get_public (&cth->identity, &cth->identity_pub); | ||
1194 | cth->attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList); | ||
1195 | cth->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList); | ||
1196 | cth->ticket = *ticket; | ||
1197 | cth->cb = cb; | ||
1198 | cth->cb_cls = cb_cls; | ||
1199 | label = | ||
1200 | GNUNET_STRINGS_data_to_string_alloc (&cth->ticket.rnd, | ||
1201 | sizeof(cth->ticket.rnd)); | ||
1202 | char *str = GNUNET_CRYPTO_public_key_to_string (&cth->ticket.identity); | ||
1203 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1204 | "Looking for AuthZ info under %s in %s\n", | ||
1205 | label, str); | ||
1206 | GNUNET_free (str); | ||
1207 | cth->lookup_start_time = GNUNET_TIME_absolute_get (); | ||
1208 | cth->lookup_request = | ||
1209 | GNUNET_GNS_lookup (gns, | ||
1210 | label, | ||
1211 | &cth->ticket.identity, | ||
1212 | GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF, | ||
1213 | GNUNET_GNS_LO_DEFAULT, | ||
1214 | &lookup_authz_cb, | ||
1215 | cth); | ||
1216 | GNUNET_free (label); | ||
1217 | return cth; | ||
1218 | } | ||
1219 | |||
1220 | |||
1221 | /** | ||
1222 | * Cancel a consume operation | ||
1223 | * | ||
1224 | * @param cth the operation to cancel | ||
1225 | */ | ||
1226 | void | ||
1227 | RECLAIM_TICKETS_consume_cancel (struct RECLAIM_TICKETS_ConsumeHandle *cth) | ||
1228 | { | ||
1229 | cleanup_cth (cth); | ||
1230 | return; | ||
1231 | } | ||
1232 | |||
1233 | |||
1234 | /******************************* | ||
1235 | * Ticket issue | ||
1236 | *******************************/ | ||
1237 | |||
1238 | /** | ||
1239 | * Cleanup ticket consume handle | ||
1240 | * @param handle the handle to clean up | ||
1241 | */ | ||
1242 | static void | ||
1243 | cleanup_issue_handle (struct TicketIssueHandle *handle) | ||
1244 | { | ||
1245 | if (NULL != handle->ns_qe) | ||
1246 | GNUNET_NAMESTORE_cancel (handle->ns_qe); | ||
1247 | GNUNET_free (handle); | ||
1248 | } | ||
1249 | |||
1250 | |||
1251 | /** | ||
1252 | * Store finished, abort on error. | ||
1253 | * Else, return new ticket to caller. | ||
1254 | * | ||
1255 | * @param cls handle to the operation | ||
1256 | * @param success store operation result | ||
1257 | * @param emsg error message (or NULL on success) | ||
1258 | */ | ||
1259 | static void | ||
1260 | store_ticket_issue_cont (void *cls, enum GNUNET_ErrorCode ec) | ||
1261 | { | ||
1262 | struct TicketIssueHandle *handle = cls; | ||
1263 | |||
1264 | handle->ns_qe = NULL; | ||
1265 | if (GNUNET_EC_NONE != ec) | ||
1266 | { | ||
1267 | handle->cb (handle->cb_cls, | ||
1268 | &handle->ticket, | ||
1269 | NULL, | ||
1270 | GNUNET_SYSERR, | ||
1271 | "Error storing AuthZ ticket in GNS"); | ||
1272 | return; | ||
1273 | } | ||
1274 | handle->cb (handle->cb_cls, | ||
1275 | &handle->ticket, | ||
1276 | handle->presentations, | ||
1277 | GNUNET_OK, NULL); | ||
1278 | cleanup_issue_handle (handle); | ||
1279 | } | ||
1280 | |||
1281 | |||
1282 | /** | ||
1283 | * Issue a new ticket. | ||
1284 | * We store references to attribute record labels and the ticket itself | ||
1285 | * under the label base64(ticket.rnd). | ||
1286 | * | ||
1287 | * @param ih handle to the operation containing relevant metadata | ||
1288 | */ | ||
1289 | static void | ||
1290 | issue_ticket (struct TicketIssueHandle *ih) | ||
1291 | { | ||
1292 | struct GNUNET_RECLAIM_AttributeListEntry *le; | ||
1293 | struct GNUNET_RECLAIM_PresentationListEntry *ple; | ||
1294 | struct GNUNET_GNSRECORD_Data *attrs_record; | ||
1295 | char *label; | ||
1296 | char *tkt_data; | ||
1297 | int i; | ||
1298 | int j; | ||
1299 | int attrs_count = 0; | ||
1300 | |||
1301 | for (le = ih->attrs->list_head; NULL != le; le = le->next) | ||
1302 | attrs_count++; | ||
1303 | |||
1304 | // Worst case we have one presentation per attribute | ||
1305 | attrs_record = | ||
1306 | GNUNET_malloc (2 * attrs_count * sizeof(struct GNUNET_GNSRECORD_Data)); | ||
1307 | i = 0; | ||
1308 | for (le = ih->attrs->list_head; NULL != le; le = le->next) | ||
1309 | { | ||
1310 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1311 | "Adding list entry: %s\n", le->attribute->name); | ||
1312 | |||
1313 | attrs_record[i].data = &le->attribute->id; | ||
1314 | attrs_record[i].data_size = sizeof(le->attribute->id); | ||
1315 | attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us; | ||
1316 | attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF; | ||
1317 | attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1318 | i++; | ||
1319 | if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential)) | ||
1320 | { | ||
1321 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1322 | "Attribute is backed by credential. Adding...\n"); | ||
1323 | struct GNUNET_RECLAIM_Presentation *presentation = NULL; | ||
1324 | for (j = 0; j < i; j++) | ||
1325 | { | ||
1326 | if (attrs_record[j].record_type | ||
1327 | != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION) | ||
1328 | continue; | ||
1329 | presentation = GNUNET_RECLAIM_presentation_deserialize ( | ||
1330 | attrs_record[j].data, | ||
1331 | attrs_record[j]. | ||
1332 | data_size); | ||
1333 | if (NULL == presentation) | ||
1334 | { | ||
1335 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1336 | "Failed to deserialize presentation\n"); | ||
1337 | continue; | ||
1338 | } | ||
1339 | if (0 == memcmp (&presentation->credential_id, | ||
1340 | &le->attribute->credential, | ||
1341 | sizeof (le->attribute->credential))) | ||
1342 | break; | ||
1343 | GNUNET_free (presentation); | ||
1344 | presentation = NULL; | ||
1345 | } | ||
1346 | if (NULL != presentation) | ||
1347 | { | ||
1348 | GNUNET_free (presentation); | ||
1349 | continue; // Skip as we have already added this credential presentation. | ||
1350 | } | ||
1351 | for (ple = ih->presentations->list_head; NULL != ple; ple = ple->next) | ||
1352 | { | ||
1353 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1354 | "Checking presentation....\n"); | ||
1355 | |||
1356 | if (0 != memcmp (&le->attribute->credential, | ||
1357 | &ple->presentation->credential_id, | ||
1358 | sizeof (le->attribute->credential))) | ||
1359 | { | ||
1360 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1361 | "Presentation does not match credential ID.\n"); | ||
1362 | continue; | ||
1363 | } | ||
1364 | char *pres_buf; | ||
1365 | size_t pres_size; | ||
1366 | |||
1367 | pres_size = | ||
1368 | GNUNET_RECLAIM_presentation_serialize_get_size (ple->presentation); | ||
1369 | pres_buf = GNUNET_malloc (pres_size); | ||
1370 | GNUNET_RECLAIM_presentation_serialize (ple->presentation, | ||
1371 | pres_buf); | ||
1372 | attrs_record[i].data = pres_buf; | ||
1373 | attrs_record[i].data_size = pres_size; | ||
1374 | attrs_record[i].expiration_time = | ||
1375 | ticket_refresh_interval.rel_value_us; | ||
1376 | attrs_record[i].record_type = | ||
1377 | GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION; | ||
1378 | attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1379 | i++; | ||
1380 | break; | ||
1381 | } | ||
1382 | } | ||
1383 | } | ||
1384 | attrs_record[i].data_size = | ||
1385 | GNUNET_RECLAIM_ticket_serialize_get_size (&ih->ticket); | ||
1386 | tkt_data = GNUNET_malloc (attrs_record[i].data_size); | ||
1387 | GNUNET_RECLAIM_write_ticket_to_buffer (&ih->ticket, | ||
1388 | tkt_data, | ||
1389 | attrs_record[i].data_size); | ||
1390 | attrs_record[i].data = tkt_data; | ||
1391 | attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us; | ||
1392 | attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET; | ||
1393 | attrs_record[i].flags = | ||
1394 | GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE; | ||
1395 | i++; | ||
1396 | |||
1397 | label = | ||
1398 | GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd, | ||
1399 | sizeof(ih->ticket.rnd)); | ||
1400 | struct GNUNET_CRYPTO_PublicKey pub; | ||
1401 | GNUNET_CRYPTO_key_get_public (&ih->identity, | ||
1402 | &pub); | ||
1403 | char *str = GNUNET_CRYPTO_public_key_to_string (&pub); | ||
1404 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1405 | "Storing AuthZ information under %s in %s\n", label, str); | ||
1406 | GNUNET_free (str); | ||
1407 | // Publish record | ||
1408 | ih->ns_qe = GNUNET_NAMESTORE_records_store (nsh, | ||
1409 | &ih->identity, | ||
1410 | label, | ||
1411 | i, | ||
1412 | attrs_record, | ||
1413 | &store_ticket_issue_cont, | ||
1414 | ih); | ||
1415 | for (j = 0; j < i; j++) | ||
1416 | { | ||
1417 | if (attrs_record[j].record_type | ||
1418 | != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION) | ||
1419 | continue; | ||
1420 | // Yes, we are allowed to do this because we allocated it above | ||
1421 | char *ptr = (char*) attrs_record[j].data; | ||
1422 | GNUNET_free (ptr); | ||
1423 | } | ||
1424 | GNUNET_free (tkt_data); | ||
1425 | GNUNET_free (attrs_record); | ||
1426 | GNUNET_free (label); | ||
1427 | } | ||
1428 | |||
1429 | |||
1430 | /************************************************* | ||
1431 | * Ticket iteration (finding a specific ticket) | ||
1432 | *************************************************/ | ||
1433 | |||
1434 | |||
1435 | /** | ||
1436 | * Namestore error on issue. Abort. | ||
1437 | * | ||
1438 | * @param cls handle to the operation | ||
1439 | */ | ||
1440 | static void | ||
1441 | filter_tickets_error_cb (void *cls) | ||
1442 | { | ||
1443 | struct TicketIssueHandle *tih = cls; | ||
1444 | |||
1445 | tih->ns_it = NULL; | ||
1446 | tih->cb (tih->cb_cls, | ||
1447 | &tih->ticket, | ||
1448 | NULL, | ||
1449 | GNUNET_SYSERR, | ||
1450 | "Error storing AuthZ ticket in GNS"); | ||
1451 | cleanup_issue_handle (tih); | ||
1452 | } | ||
1453 | |||
1454 | |||
1455 | /** | ||
1456 | * Iterator over records. | ||
1457 | * Check if any previously issued ticket already | ||
1458 | * matches what we need to prevent duplicates and | ||
1459 | * improve resolution synergy. | ||
1460 | * | ||
1461 | * @param cls handle to the operation | ||
1462 | * @param zone issuer identity | ||
1463 | * @param label ticket rnd | ||
1464 | * @param rd_count size of record set | ||
1465 | * @param rd record set | ||
1466 | */ | ||
1467 | static void | ||
1468 | filter_tickets_cb (void *cls, | ||
1469 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
1470 | const char *label, | ||
1471 | unsigned int rd_count, | ||
1472 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1473 | { | ||
1474 | struct TicketIssueHandle *tih = cls; | ||
1475 | struct GNUNET_RECLAIM_Ticket ticket; | ||
1476 | struct GNUNET_RECLAIM_Presentation *presentation; | ||
1477 | struct GNUNET_RECLAIM_PresentationList *ticket_presentations; | ||
1478 | struct GNUNET_RECLAIM_Credential *cred; | ||
1479 | struct GNUNET_RECLAIM_PresentationListEntry *ple; | ||
1480 | struct GNUNET_RECLAIM_AttributeListEntry *le; | ||
1481 | unsigned int attr_cnt = 0; | ||
1482 | unsigned int pres_cnt = 0; | ||
1483 | int ticket_found = GNUNET_NO; | ||
1484 | |||
1485 | for (le = tih->attrs->list_head; NULL != le; le = le->next) | ||
1486 | { | ||
1487 | attr_cnt++; | ||
1488 | if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential)) | ||
1489 | pres_cnt++; | ||
1490 | } | ||
1491 | |||
1492 | // ticket search | ||
1493 | unsigned int found_attrs_cnt = 0; | ||
1494 | unsigned int found_pres_cnt = 0; | ||
1495 | size_t read; | ||
1496 | ticket_presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList); | ||
1497 | |||
1498 | for (int i = 0; i < rd_count; i++) | ||
1499 | { | ||
1500 | // found ticket | ||
1501 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET == rd[i].record_type) | ||
1502 | { | ||
1503 | if ((GNUNET_SYSERR == | ||
1504 | GNUNET_RECLAIM_read_ticket_from_buffer (rd[i].data, | ||
1505 | rd[i].data_size, | ||
1506 | &ticket, | ||
1507 | &read)) || | ||
1508 | (read != rd[i].data_size)) | ||
1509 | { | ||
1510 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1511 | "Failed to deserialize ticket from record\n"); | ||
1512 | continue; | ||
1513 | } | ||
1514 | // cmp audience | ||
1515 | // FIXME this is ugly, GNUNET_CRYPTO_PublicKey cannot be compared | ||
1516 | // like this | ||
1517 | if (0 == memcmp (&tih->ticket.audience, | ||
1518 | &ticket.audience, | ||
1519 | sizeof(struct GNUNET_CRYPTO_PublicKey))) | ||
1520 | { | ||
1521 | tih->ticket = ticket; | ||
1522 | ticket_found = GNUNET_YES; | ||
1523 | continue; | ||
1524 | } | ||
1525 | } | ||
1526 | |||
1527 | // cmp requested attributes with ticket attributes | ||
1528 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type) | ||
1529 | { | ||
1530 | for (le = tih->attrs->list_head; NULL != le; le = le->next) | ||
1531 | { | ||
1532 | if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data, | ||
1533 | &le->attribute->id)) | ||
1534 | found_attrs_cnt++; | ||
1535 | } | ||
1536 | } | ||
1537 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type) | ||
1538 | { | ||
1539 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1540 | "Found credential...\n"); | ||
1541 | |||
1542 | for (le = tih->attrs->list_head; NULL != le; le = le->next) | ||
1543 | { | ||
1544 | cred = GNUNET_RECLAIM_credential_deserialize (rd[i].data, | ||
1545 | rd[i].data_size); | ||
1546 | if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (&cred->id, | ||
1547 | &le->attribute->credential)) | ||
1548 | { | ||
1549 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1550 | "No match.\n"); | ||
1551 | GNUNET_free (cred); | ||
1552 | continue; | ||
1553 | } | ||
1554 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1555 | "Match, creating presentation...\n"); | ||
1556 | if (GNUNET_OK != GNUNET_RECLAIM_credential_get_presentation ( | ||
1557 | cred, | ||
1558 | tih->attrs, | ||
1559 | &presentation)) | ||
1560 | { | ||
1561 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1562 | "Unable to retrieve presentation from credential\n"); | ||
1563 | GNUNET_free (cred); | ||
1564 | continue; | ||
1565 | } | ||
1566 | ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry); | ||
1567 | ple->presentation = presentation; | ||
1568 | GNUNET_CONTAINER_DLL_insert (tih->presentations->list_head, | ||
1569 | tih->presentations->list_tail, | ||
1570 | ple); | ||
1571 | GNUNET_free (cred); | ||
1572 | break; | ||
1573 | } | ||
1574 | } | ||
1575 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION == rd[i].record_type) | ||
1576 | { | ||
1577 | for (le = tih->attrs->list_head; NULL != le; le = le->next) | ||
1578 | { | ||
1579 | presentation = GNUNET_RECLAIM_presentation_deserialize (rd[i].data, | ||
1580 | rd[i].data_size); | ||
1581 | if (NULL == presentation) | ||
1582 | { | ||
1583 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1584 | "Failed to deserialize presentation\n"); | ||
1585 | continue; | ||
1586 | } | ||
1587 | if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal ( | ||
1588 | &presentation->credential_id, | ||
1589 | &le->attribute->credential)) | ||
1590 | { | ||
1591 | found_pres_cnt++; | ||
1592 | ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry); | ||
1593 | ple->presentation = presentation; | ||
1594 | GNUNET_CONTAINER_DLL_insert (ticket_presentations->list_head, | ||
1595 | ticket_presentations->list_tail, | ||
1596 | ple); | ||
1597 | } | ||
1598 | } | ||
1599 | } | ||
1600 | } | ||
1601 | |||
1602 | /** | ||
1603 | * If we found a matching ticket, return that to the caller and | ||
1604 | * we are done. | ||
1605 | */ | ||
1606 | if ((attr_cnt == found_attrs_cnt) && | ||
1607 | (pres_cnt == found_pres_cnt) && | ||
1608 | (GNUNET_YES == ticket_found)) | ||
1609 | { | ||
1610 | GNUNET_NAMESTORE_zone_iteration_stop (tih->ns_it); | ||
1611 | tih->cb (tih->cb_cls, &tih->ticket, ticket_presentations, GNUNET_OK, NULL); | ||
1612 | GNUNET_RECLAIM_presentation_list_destroy (ticket_presentations); | ||
1613 | cleanup_issue_handle (tih); | ||
1614 | return; | ||
1615 | } | ||
1616 | GNUNET_RECLAIM_presentation_list_destroy (ticket_presentations); | ||
1617 | // ticket not found in current record, checking next record set | ||
1618 | GNUNET_NAMESTORE_zone_iterator_next (tih->ns_it, 1); | ||
1619 | } | ||
1620 | |||
1621 | |||
1622 | /** | ||
1623 | * Done iterating over tickets and we apparently did | ||
1624 | * not find an existing, matching ticket. | ||
1625 | * Continue by issuing a new ticket. | ||
1626 | * | ||
1627 | * @param cls handle to the operation | ||
1628 | */ | ||
1629 | static void | ||
1630 | filter_tickets_finished_cb (void *cls) | ||
1631 | { | ||
1632 | struct TicketIssueHandle *tih = cls; | ||
1633 | |||
1634 | GNUNET_CRYPTO_key_get_public (&tih->identity, &tih->ticket.identity); | ||
1635 | GNUNET_RECLAIM_id_generate (&tih->ticket.rnd); | ||
1636 | issue_ticket (tih); | ||
1637 | } | ||
1638 | |||
1639 | |||
1640 | /** | ||
1641 | * Issue a new reclaim ticket, thereby authorizing | ||
1642 | * the audience to access the set of provided attributes. | ||
1643 | * | ||
1644 | * @param identity the issuer | ||
1645 | * @param attrs the attributes to share | ||
1646 | * @param audience the audience to share the attributes with | ||
1647 | * @param cb the callback to call with the ticket result | ||
1648 | * @param cb_cls the callback closure | ||
1649 | * FIXME: Return handle?? | ||
1650 | */ | ||
1651 | void | ||
1652 | RECLAIM_TICKETS_issue (const struct GNUNET_CRYPTO_PrivateKey *identity, | ||
1653 | const struct GNUNET_RECLAIM_AttributeList *attrs, | ||
1654 | const struct GNUNET_CRYPTO_PublicKey *audience, | ||
1655 | RECLAIM_TICKETS_TicketResult cb, | ||
1656 | void *cb_cls) | ||
1657 | { | ||
1658 | struct TicketIssueHandle *tih; | ||
1659 | |||
1660 | tih = GNUNET_new (struct TicketIssueHandle); | ||
1661 | tih->cb = cb; | ||
1662 | tih->cb_cls = cb_cls; | ||
1663 | tih->attrs = GNUNET_RECLAIM_attribute_list_dup (attrs); | ||
1664 | tih->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList); | ||
1665 | tih->identity = *identity; | ||
1666 | tih->ticket.audience = *audience; | ||
1667 | |||
1668 | // First check whether the ticket has already been issued | ||
1669 | tih->ns_it = | ||
1670 | GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
1671 | &tih->identity, | ||
1672 | &filter_tickets_error_cb, | ||
1673 | tih, | ||
1674 | &filter_tickets_cb, | ||
1675 | tih, | ||
1676 | &filter_tickets_finished_cb, | ||
1677 | tih); | ||
1678 | } | ||
1679 | |||
1680 | |||
1681 | /************************************ | ||
1682 | * Ticket iteration | ||
1683 | ************************************/ | ||
1684 | |||
1685 | /** | ||
1686 | * Cleanup ticket iterator | ||
1687 | * | ||
1688 | * @param iter handle to the iteration | ||
1689 | */ | ||
1690 | static void | ||
1691 | cleanup_iter (struct RECLAIM_TICKETS_Iterator *iter) | ||
1692 | { | ||
1693 | if (NULL != iter->ns_it) | ||
1694 | GNUNET_NAMESTORE_zone_iteration_stop (iter->ns_it); | ||
1695 | GNUNET_free (iter); | ||
1696 | } | ||
1697 | |||
1698 | |||
1699 | /** | ||
1700 | * Return each record of type #GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET | ||
1701 | * to the caller and proceed with the iteration. | ||
1702 | * FIXME: Should we _not_ proceed automatically here? | ||
1703 | * | ||
1704 | * @param cls handle to the iteration | ||
1705 | * @param zone the ticket issuer | ||
1706 | * @param label the ticket rnd | ||
1707 | * @param rd_count number of records in record set | ||
1708 | * @param rd record set containing a ticket | ||
1709 | */ | ||
1710 | static void | ||
1711 | collect_tickets_cb (void *cls, | ||
1712 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
1713 | const char *label, | ||
1714 | unsigned int rd_count, | ||
1715 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1716 | { | ||
1717 | struct RECLAIM_TICKETS_Iterator *iter = cls; | ||
1718 | struct GNUNET_RECLAIM_Ticket ticket; | ||
1719 | size_t read; | ||
1720 | |||
1721 | for (int i = 0; i < rd_count; i++) | ||
1722 | { | ||
1723 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET != rd[i].record_type) | ||
1724 | continue; | ||
1725 | if ((GNUNET_SYSERR == | ||
1726 | GNUNET_RECLAIM_read_ticket_from_buffer (rd[i].data, | ||
1727 | rd[i].data_size, | ||
1728 | &ticket, | ||
1729 | &read)) || | ||
1730 | (read != rd[i].data_size)) | ||
1731 | { | ||
1732 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1733 | "Failed to deserialize ticket from record\n"); | ||
1734 | continue; | ||
1735 | } | ||
1736 | iter->cb (iter->cb_cls, &ticket); | ||
1737 | return; | ||
1738 | } | ||
1739 | GNUNET_NAMESTORE_zone_iterator_next (iter->ns_it, 1); | ||
1740 | } | ||
1741 | |||
1742 | |||
1743 | /** | ||
1744 | * Signal ticket iteration has finished | ||
1745 | * | ||
1746 | * @param cls handle to the iteration | ||
1747 | */ | ||
1748 | static void | ||
1749 | collect_tickets_finished_cb (void *cls) | ||
1750 | { | ||
1751 | struct RECLAIM_TICKETS_Iterator *iter = cls; | ||
1752 | |||
1753 | iter->ns_it = NULL; | ||
1754 | iter->cb (iter->cb_cls, NULL); | ||
1755 | cleanup_iter (iter); | ||
1756 | } | ||
1757 | |||
1758 | |||
1759 | /** | ||
1760 | * Cancel ticket iteration on namestore error | ||
1761 | * | ||
1762 | * @param cls the iteration handle | ||
1763 | */ | ||
1764 | static void | ||
1765 | collect_tickets_error_cb (void *cls) | ||
1766 | { | ||
1767 | struct RECLAIM_TICKETS_Iterator *iter = cls; | ||
1768 | |||
1769 | iter->ns_it = NULL; | ||
1770 | iter->cb (iter->cb_cls, NULL); | ||
1771 | cleanup_iter (iter); | ||
1772 | } | ||
1773 | |||
1774 | |||
1775 | /** | ||
1776 | * Continue ticket iteration | ||
1777 | * | ||
1778 | * @param iter the iteration to continue | ||
1779 | */ | ||
1780 | void | ||
1781 | RECLAIM_TICKETS_iteration_next (struct RECLAIM_TICKETS_Iterator *iter) | ||
1782 | { | ||
1783 | GNUNET_NAMESTORE_zone_iterator_next (iter->ns_it, 1); | ||
1784 | } | ||
1785 | |||
1786 | |||
1787 | /** | ||
1788 | * Stop a running ticket iteration | ||
1789 | * | ||
1790 | * @param iter iteration to cancel | ||
1791 | */ | ||
1792 | void | ||
1793 | RECLAIM_TICKETS_iteration_stop (struct RECLAIM_TICKETS_Iterator *iter) | ||
1794 | { | ||
1795 | GNUNET_NAMESTORE_zone_iteration_stop (iter->ns_it); | ||
1796 | cleanup_iter (iter); | ||
1797 | } | ||
1798 | |||
1799 | |||
1800 | /** | ||
1801 | * Iterate over all tickets issued by an identity | ||
1802 | * | ||
1803 | * @param identity the issuing identity | ||
1804 | * @param cb ticket callback function | ||
1805 | * @param cb_cls callback closure | ||
1806 | * @return a handle to the iteration | ||
1807 | */ | ||
1808 | struct RECLAIM_TICKETS_Iterator * | ||
1809 | RECLAIM_TICKETS_iteration_start ( | ||
1810 | const struct GNUNET_CRYPTO_PrivateKey *identity, | ||
1811 | RECLAIM_TICKETS_TicketIter cb, | ||
1812 | void *cb_cls) | ||
1813 | { | ||
1814 | struct RECLAIM_TICKETS_Iterator *iter; | ||
1815 | |||
1816 | iter = GNUNET_new (struct RECLAIM_TICKETS_Iterator); | ||
1817 | iter->cb = cb; | ||
1818 | iter->cb_cls = cb_cls; | ||
1819 | iter->ns_it = | ||
1820 | GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
1821 | identity, | ||
1822 | &collect_tickets_error_cb, | ||
1823 | iter, | ||
1824 | &collect_tickets_cb, | ||
1825 | iter, | ||
1826 | &collect_tickets_finished_cb, | ||
1827 | iter); | ||
1828 | return iter; | ||
1829 | } | ||
1830 | |||
1831 | |||
1832 | /** | ||
1833 | * Initialize tickets component | ||
1834 | * | ||
1835 | * @param c the configuration | ||
1836 | * @return GNUNET_SYSERR on error | ||
1837 | */ | ||
1838 | int | ||
1839 | RECLAIM_TICKETS_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
1840 | { | ||
1841 | // Get ticket expiration time (relative) from config | ||
1842 | if (GNUNET_OK == | ||
1843 | GNUNET_CONFIGURATION_get_value_time (c, | ||
1844 | "reclaim", | ||
1845 | "TICKET_REFRESH_INTERVAL", | ||
1846 | &ticket_refresh_interval)) | ||
1847 | { | ||
1848 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1849 | "Configured refresh interval for tickets: %s\n", | ||
1850 | GNUNET_STRINGS_relative_time_to_string (ticket_refresh_interval, | ||
1851 | GNUNET_YES)); | ||
1852 | } | ||
1853 | else | ||
1854 | { | ||
1855 | ticket_refresh_interval = DEFAULT_TICKET_REFRESH_INTERVAL; | ||
1856 | } | ||
1857 | // Connect to identity and namestore services | ||
1858 | nsh = GNUNET_NAMESTORE_connect (c); | ||
1859 | if (NULL == nsh) | ||
1860 | { | ||
1861 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
1862 | "error connecting to namestore"); | ||
1863 | return GNUNET_SYSERR; | ||
1864 | } | ||
1865 | gns = GNUNET_GNS_connect (c); | ||
1866 | if (NULL == gns) | ||
1867 | { | ||
1868 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns"); | ||
1869 | return GNUNET_SYSERR; | ||
1870 | } | ||
1871 | stats = GNUNET_STATISTICS_create ("reclaim", c); | ||
1872 | return GNUNET_OK; | ||
1873 | } | ||
1874 | |||
1875 | |||
1876 | /** | ||
1877 | * Close handles and clean up. | ||
1878 | * FIXME: cancel all pending operations (gns, ns etc) | ||
1879 | */ | ||
1880 | void | ||
1881 | RECLAIM_TICKETS_deinit (void) | ||
1882 | { | ||
1883 | if (NULL != nsh) | ||
1884 | GNUNET_NAMESTORE_disconnect (nsh); | ||
1885 | nsh = NULL; | ||
1886 | if (NULL != gns) | ||
1887 | GNUNET_GNS_disconnect (gns); | ||
1888 | gns = NULL; | ||
1889 | if (NULL != stats) | ||
1890 | { | ||
1891 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | ||
1892 | stats = NULL; | ||
1893 | } | ||
1894 | } | ||