aboutsummaryrefslogtreecommitdiff
path: root/src/abd/gnunet-service-abd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/abd/gnunet-service-abd.c')
-rw-r--r--src/abd/gnunet-service-abd.c1779
1 files changed, 0 insertions, 1779 deletions
diff --git a/src/abd/gnunet-service-abd.c b/src/abd/gnunet-service-abd.c
deleted file mode 100644
index 407d5bdc3..000000000
--- a/src/abd/gnunet-service-abd.c
+++ /dev/null
@@ -1,1779 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2013 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 * @file abd/gnunet-service-abd.c
22 * @brief GNUnet Credential Service (main service)
23 * @author Martin Schanzenbach
24 */
25#include "platform.h"
26
27#include "gnunet_util_lib.h"
28
29#include "abd.h"
30#include "abd_serialization.h"
31#include "gnunet_abd_service.h"
32#include "gnunet_protocols.h"
33#include "gnunet_signatures.h"
34#include "gnunet_statistics_service.h"
35#include <gnunet_dnsparser_lib.h>
36#include <gnunet_gns_service.h>
37#include <gnunet_gnsrecord_lib.h>
38#include <gnunet_identity_service.h>
39#include <gnunet_namestore_service.h>
40
41
42#define GNUNET_ABD_MAX_LENGTH 255
43
44struct VerifyRequestHandle;
45
46struct DelegationSetQueueEntry;
47
48
49struct DelegationChainEntry
50{
51 /**
52 * DLL
53 */
54 struct DelegationChainEntry *next;
55
56 /**
57 * DLL
58 */
59 struct DelegationChainEntry *prev;
60
61 /**
62 * The issuer
63 */
64 struct GNUNET_IDENTITY_PublicKey issuer_key;
65
66 /**
67 * The subject
68 */
69 struct GNUNET_IDENTITY_PublicKey subject_key;
70
71 /**
72 * The issued attribute
73 */
74 char *issuer_attribute;
75
76 /**
77 * The delegated attribute
78 */
79 char *subject_attribute;
80};
81
82/**
83 * DLL for record
84 */
85struct DelegateRecordEntry
86{
87 /**
88 * DLL
89 */
90 struct DelegateRecordEntry *next;
91
92 /**
93 * DLL
94 */
95 struct DelegateRecordEntry *prev;
96
97 /**
98 * Number of references in delegation chains
99 */
100 uint32_t refcount;
101
102 /**
103 * Payload
104 */
105 struct GNUNET_ABD_Delegate *delegate;
106};
107
108/**
109 * DLL used for delegations
110 * Used for OR delegations
111 */
112struct DelegationQueueEntry
113{
114 /**
115 * DLL
116 */
117 struct DelegationQueueEntry *next;
118
119 /**
120 * DLL
121 */
122 struct DelegationQueueEntry *prev;
123
124 /**
125 * Parent set
126 */
127 struct DelegationSetQueueEntry *parent_set;
128
129 /**
130 * Required solutions
131 */
132 uint32_t required_solutions;
133};
134
135/**
136 * DLL for delegation sets
137 * Used for AND delegation set
138 */
139struct DelegationSetQueueEntry
140{
141 /**
142 * DLL
143 */
144 struct DelegationSetQueueEntry *next;
145
146 /**
147 * DLL
148 */
149 struct DelegationSetQueueEntry *prev;
150
151 /**
152 * GNS handle
153 */
154 struct GNUNET_GNS_LookupRequest *lookup_request;
155
156 /**
157 * Verify handle
158 */
159 struct VerifyRequestHandle *handle;
160
161 /**
162 * Parent attribute delegation
163 */
164 struct DelegationQueueEntry *parent;
165
166 /**
167 * Issuer key
168 */
169 struct GNUNET_IDENTITY_PublicKey *issuer_key;
170
171 /**
172 * Queue entries of this set
173 */
174 struct DelegationQueueEntry *queue_entries_head;
175
176 /**
177 * Queue entries of this set
178 */
179 struct DelegationQueueEntry *queue_entries_tail;
180
181 /**
182 * Parent QueueEntry
183 */
184 struct DelegationQueueEntry *parent_queue_entry;
185
186 /**
187 * Issuer attribute delegated to
188 */
189 char *issuer_attribute;
190
191 /**
192 * The current attribute to look up
193 */
194 char *lookup_attribute;
195
196 /**
197 * Trailing attribute context
198 */
199 char *attr_trailer;
200
201 /**
202 * Still to resolve delegation as string
203 */
204 char *unresolved_attribute_delegation;
205
206 /**
207 * The delegation chain entry
208 */
209 struct DelegationChainEntry *delegation_chain_entry;
210
211 /**
212 * True if added by backward resolution
213 */
214 bool from_bw;
215};
216
217
218/**
219 * Handle to a lookup operation from api
220 */
221struct VerifyRequestHandle
222{
223 /**
224 * True if created by a collect request.
225 */
226 bool is_collect;
227 /**
228 * We keep these in a DLL.
229 */
230 struct VerifyRequestHandle *next;
231
232 /**
233 * We keep these in a DLL.
234 */
235 struct VerifyRequestHandle *prev;
236
237 /**
238 * Handle to the requesting client
239 */
240 struct GNUNET_SERVICE_Client *client;
241
242 /**
243 * Size of delegation tree
244 */
245 uint32_t delegation_chain_size;
246
247 /**
248 * Children of this attribute
249 */
250 struct DelegationChainEntry *delegation_chain_head;
251
252 /**
253 * Children of this attribute
254 */
255 struct DelegationChainEntry *delegation_chain_tail;
256
257 /**
258 * List for bidirectional matching
259 */
260 struct DelegationSetQueueEntry *dsq_head;
261
262 /**
263 * List for bidirectional matching
264 */
265 struct DelegationSetQueueEntry *dsq_tail;
266
267 /**
268 * Issuer public key
269 */
270 struct GNUNET_IDENTITY_PublicKey issuer_key;
271
272 /**
273 * Issuer attribute
274 */
275 char *issuer_attribute;
276
277 /**
278 * Subject public key
279 */
280 struct GNUNET_IDENTITY_PublicKey subject_key;
281
282 /**
283 * Delegate DLL
284 */
285 struct DelegateRecordEntry *del_chain_head;
286
287 /**
288 * Delegate DLL
289 */
290 struct DelegateRecordEntry *del_chain_tail;
291
292 /**
293 * Delegate DLL size
294 */
295 uint32_t del_chain_size;
296
297 /**
298 * Current Delegation Pointer
299 */
300 struct DelegationQueueEntry *current_delegation;
301
302 /**
303 * request id
304 */
305 uint32_t request_id;
306
307 /**
308 * Pending lookups
309 */
310 uint64_t pending_lookups;
311
312 /**
313 * Direction of the resolution algo
314 */
315 enum GNUNET_ABD_AlgoDirectionFlags resolution_algo;
316
317 /**
318 * Delegate iterator for lookup
319 */
320 struct GNUNET_NAMESTORE_QueueEntry *dele_qe;
321};
322
323
324/**
325 * Head of the DLL.
326 */
327static struct VerifyRequestHandle *vrh_head = NULL;
328
329/**
330 * Tail of the DLL.
331 */
332static struct VerifyRequestHandle *vrh_tail = NULL;
333
334/**
335 * Handle to the statistics service
336 */
337static struct GNUNET_STATISTICS_Handle *statistics;
338
339/**
340 * Handle to GNS service.
341 */
342static struct GNUNET_GNS_Handle *gns;
343
344/**
345 * Handle to namestore service
346 */
347static struct GNUNET_NAMESTORE_Handle *namestore;
348
349static void
350print_deleset (struct DelegationSetQueueEntry *dsentry, char *text)
351{
352 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
353 "%s %s.%s <- %s.%s\n",
354 text,
355 GNUNET_IDENTITY_public_key_to_string (
356 &dsentry->delegation_chain_entry->issuer_key),
357 dsentry->delegation_chain_entry->issuer_attribute,
358 GNUNET_IDENTITY_public_key_to_string (
359 &dsentry->delegation_chain_entry->subject_key),
360 dsentry->delegation_chain_entry->subject_attribute);
361}
362
363
364static void
365cleanup_dsq_entry (struct DelegationSetQueueEntry *ds_entry)
366{
367 GNUNET_free (ds_entry->issuer_key);
368 GNUNET_free (ds_entry->issuer_attribute);
369 GNUNET_free (ds_entry->attr_trailer);
370 // those fields are only set/used in bw search
371 if (ds_entry->from_bw)
372 {
373 GNUNET_free (ds_entry->lookup_attribute);
374 GNUNET_free (ds_entry->unresolved_attribute_delegation);
375 }
376 if (NULL != ds_entry->lookup_request)
377 {
378 GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
379 ds_entry->lookup_request = NULL;
380 }
381 if (NULL != ds_entry->delegation_chain_entry)
382 {
383 GNUNET_free (
384 ds_entry->delegation_chain_entry->subject_attribute);
385 GNUNET_free (ds_entry->delegation_chain_entry->issuer_attribute);
386 GNUNET_free (ds_entry->delegation_chain_entry);
387 }
388 // Free DQ entries
389 for (struct DelegationQueueEntry *dq_entry = ds_entry->queue_entries_head;
390 NULL != ds_entry->queue_entries_head;
391 dq_entry = ds_entry->queue_entries_head)
392 {
393 GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
394 ds_entry->queue_entries_tail,
395 dq_entry);
396 GNUNET_free (dq_entry);
397 }
398 GNUNET_free (ds_entry);
399}
400
401
402static void
403cleanup_handle (struct VerifyRequestHandle *vrh)
404{
405 struct DelegateRecordEntry *del_entry;
406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up...\n");
407
408 if (NULL != vrh->dsq_head)
409 {
410 for (struct DelegationSetQueueEntry *ds_entry = vrh->dsq_head; NULL !=
411 vrh->dsq_head;
412 ds_entry = vrh->dsq_head)
413 {
414 GNUNET_CONTAINER_DLL_remove (vrh->dsq_head, vrh->dsq_tail, ds_entry);
415 cleanup_dsq_entry (ds_entry);
416 }
417 }
418 if (NULL != vrh->del_chain_head)
419 {
420 for (del_entry = vrh->del_chain_head; NULL != vrh->del_chain_head;
421 del_entry = vrh->del_chain_head)
422 {
423 GNUNET_CONTAINER_DLL_remove (vrh->del_chain_head,
424 vrh->del_chain_tail,
425 del_entry);
426 GNUNET_free (del_entry->delegate);
427 GNUNET_free (del_entry);
428 }
429 }
430 GNUNET_free (vrh->issuer_attribute);
431 GNUNET_free (vrh);
432}
433
434
435static void
436shutdown_task (void *cls)
437{
438 struct VerifyRequestHandle *vrh;
439
440 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down!\n");
441
442 while (NULL != (vrh = vrh_head))
443 {
444 // ABD_resolver_lookup_cancel (clh->lookup);
445 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
446 cleanup_handle (vrh);
447 }
448
449 if (NULL != gns)
450 {
451 GNUNET_GNS_disconnect (gns);
452 gns = NULL;
453 }
454 if (NULL != namestore)
455 {
456 GNUNET_NAMESTORE_disconnect (namestore);
457 namestore = NULL;
458 }
459 if (NULL != statistics)
460 {
461 GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
462 statistics = NULL;
463 }
464}
465
466
467static void
468send_intermediate_response (struct VerifyRequestHandle *vrh, struct
469 DelegationChainEntry *ch_entry, bool is_bw)
470{
471 struct DelegationChainIntermediateMessage *rmsg;
472 struct GNUNET_MQ_Envelope *env;
473 struct GNUNET_ABD_Delegation *dd;
474 size_t size;
475
476 // Don't report immediate results during collect
477 if (vrh->is_collect)
478 return;
479
480 dd = GNUNET_new (struct GNUNET_ABD_Delegation);
481 dd->issuer_key = ch_entry->issuer_key;
482 dd->subject_key = ch_entry->subject_key;
483 dd->issuer_attribute = ch_entry->issuer_attribute;
484 dd->issuer_attribute_len = strlen (ch_entry->issuer_attribute) + 1;
485 dd->subject_attribute_len = 0;
486 dd->subject_attribute = NULL;
487 if (NULL != ch_entry->subject_attribute)
488 {
489 dd->subject_attribute = ch_entry->subject_attribute;
490 dd->subject_attribute_len = strlen (ch_entry->subject_attribute) + 1;
491 }
492
493
494 size = GNUNET_ABD_delegation_chain_get_size (1,
495 dd,
496 0,
497 NULL);
498
499 env = GNUNET_MQ_msg_extra (rmsg,
500 size,
501 GNUNET_MESSAGE_TYPE_ABD_INTERMEDIATE_RESULT);
502 // Assign id so that client can find associated request
503 rmsg->id = vrh->request_id;
504 rmsg->is_bw = htons (is_bw);
505 rmsg->size = htonl (size);
506
507 GNUNET_assert (
508 -1 != GNUNET_ABD_delegation_chain_serialize (1,
509 dd,
510 0,
511 NULL,
512 size,
513 (char *) &rmsg[1]));
514 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (vrh->client), env);
515
516 GNUNET_free (dd);
517}
518
519
520static void
521send_lookup_response (struct VerifyRequestHandle *vrh)
522{
523 struct GNUNET_MQ_Envelope *env;
524 struct DelegationChainResultMessage *rmsg;
525 struct DelegationChainEntry *dce;
526 struct GNUNET_ABD_Delegation dd[vrh->delegation_chain_size];
527 struct GNUNET_ABD_Delegate dele[vrh->del_chain_size];
528 struct DelegateRecordEntry *del;
529 struct DelegateRecordEntry *tmp;
530 size_t size;
531
532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending response\n");
533 dce = vrh->delegation_chain_head;
534 for (uint32_t i = 0; i < vrh->delegation_chain_size; i++)
535 {
536 dd[i].issuer_key = dce->issuer_key;
537 dd[i].subject_key = dce->subject_key;
538 dd[i].issuer_attribute = dce->issuer_attribute;
539 dd[i].issuer_attribute_len = strlen (dce->issuer_attribute) + 1;
540 dd[i].subject_attribute_len = 0;
541 dd[i].subject_attribute = NULL;
542 if (NULL != dce->subject_attribute)
543 {
544 dd[i].subject_attribute = dce->subject_attribute;
545 dd[i].subject_attribute_len = strlen (dce->subject_attribute) + 1;
546 }
547 dce = dce->next;
548 }
549
550 // Remove all not needed credentials
551 for (del = vrh->del_chain_head; NULL != del;)
552 {
553 if (del->refcount > 0)
554 {
555 del = del->next;
556 continue;
557 }
558 tmp = del;
559 del = del->next;
560 GNUNET_CONTAINER_DLL_remove (vrh->del_chain_head, vrh->del_chain_tail, tmp);
561 GNUNET_free (tmp->delegate);
562 GNUNET_free (tmp);
563 vrh->del_chain_size--;
564 }
565
566 // Get serialized record data
567 // Append at the end of rmsg
568 del = vrh->del_chain_head;
569 for (uint32_t i = 0; i < vrh->del_chain_size; i++)
570 {
571 dele[i].issuer_key = del->delegate->issuer_key;
572 dele[i].subject_key = del->delegate->subject_key;
573 dele[i].issuer_attribute_len = strlen (del->delegate->issuer_attribute) + 1;
574 dele[i].issuer_attribute = del->delegate->issuer_attribute;
575 dele[i].subject_attribute_len = del->delegate->subject_attribute_len;
576 dele[i].subject_attribute = del->delegate->subject_attribute;
577 dele[i].expiration = del->delegate->expiration;
578 dele[i].signature = del->delegate->signature;
579 del = del->next;
580 }
581 size =
582 GNUNET_ABD_delegation_chain_get_size (vrh->delegation_chain_size,
583 dd,
584 vrh->del_chain_size,
585 dele);
586 env = GNUNET_MQ_msg_extra (rmsg,
587 size,
588 GNUNET_MESSAGE_TYPE_ABD_VERIFY_RESULT);
589 // Assign id so that client can find associated request
590 rmsg->id = vrh->request_id;
591 rmsg->d_count = htonl (vrh->delegation_chain_size);
592 rmsg->c_count = htonl (vrh->del_chain_size);
593
594 if (0 < vrh->del_chain_size)
595 rmsg->del_found = htonl (GNUNET_YES);
596 else
597 rmsg->del_found = htonl (GNUNET_NO);
598
599 GNUNET_assert (
600 -1 !=
601 GNUNET_ABD_delegation_chain_serialize (vrh->delegation_chain_size,
602 dd,
603 vrh->del_chain_size,
604 dele,
605 size,
606 (char *) &rmsg[1]));
607
608 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (vrh->client), env);
609 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
610 cleanup_handle (vrh);
611 GNUNET_STATISTICS_update (statistics,
612 "Completed verifications",
613 1,
614 GNUNET_NO);
615}
616
617
618static char *
619partial_match (char *tmp_trail,
620 char *tmp_subattr,
621 char *parent_trail,
622 char *issuer_attribute)
623{
624 char *saveptr1, *saveptr2;
625 char *trail_token;
626 char *sub_token;
627 char *attr_trailer;
628
629 // tok both, parent->attr_trailer and del->sub_attr to see how far they match,
630 // take rest of parent trailer (only when del->sub_attr token is null), and
631 // create new/actual trailer with del->iss_attr
632 trail_token = strtok_r (tmp_trail, ".", &saveptr1);
633 sub_token = strtok_r (tmp_subattr, ".", &saveptr2);
634 while (NULL != trail_token && NULL != sub_token)
635 {
636 if (0 == strcmp (trail_token, sub_token))
637 {
638 // good, matches, remove
639 }
640 else
641 {
642 // not relevant for solving the chain, end for iteration here
643 return NULL;
644 }
645
646 trail_token = strtok_r (NULL, ".", &saveptr1);
647 sub_token = strtok_r (NULL, ".", &saveptr2);
648 }
649 // skip this entry and go to next for if:
650 // 1. at some point the attr of the trailer and the subject dont match
651 // 2. the trailer is NULL, but the subject has more attributes
652 // Reason: This will lead to "startzone.attribute" but we're looking for a solution
653 // for "<- startzone"
654 if (NULL == trail_token)
655 {
656 return NULL;
657 }
658
659 // do not have to check sub_token == NULL, if both would be NULL
660 // at the same time, the complete match part above should have triggered already
661
662 // otherwise, above while only ends when sub_token == NULL
663 GNUNET_asprintf (&attr_trailer, "%s", trail_token);
664 trail_token = strtok_r (NULL, ".", &saveptr1);
665 while (NULL != trail_token)
666 {
667 GNUNET_asprintf (&attr_trailer, "%s.%s", parent_trail, trail_token);
668 trail_token = strtok_r (NULL, ".", &saveptr1);
669 }
670 GNUNET_asprintf (&attr_trailer, "%s.%s", issuer_attribute, attr_trailer);
671 return attr_trailer;
672}
673
674
675static int
676handle_bidirectional_match (struct DelegationSetQueueEntry *actual_entry,
677 struct DelegationSetQueueEntry *match_entry,
678 struct VerifyRequestHandle *vrh)
679{
680 struct DelegationSetQueueEntry *old_fw_parent;
681 struct DelegationSetQueueEntry *fw_entry = actual_entry;
682 struct DelegationSetQueueEntry *last_entry = match_entry;
683 // parent fixing, combine backward and forward chain parts
684 while (NULL != fw_entry->parent_queue_entry)
685 {
686 old_fw_parent = fw_entry->parent_queue_entry->parent_set;
687 // set parent
688 fw_entry->parent_queue_entry->parent_set = last_entry;
689
690 last_entry = fw_entry;
691 fw_entry = old_fw_parent;
692 }
693 // set last entry of chain as actual_entry
694 // actual_entry = last_entry;
695 // set refcount, loop all delegations
696 for (struct DelegateRecordEntry *del_entry = vrh->del_chain_head;
697 del_entry != NULL;
698 del_entry = del_entry->next)
699 {
700 if (0 != memcmp (&last_entry->delegation_chain_entry->subject_key,
701 &del_entry->delegate->issuer_key,
702 sizeof (struct GNUNET_IDENTITY_PublicKey)))
703 continue;
704 if (0 != strcmp (last_entry->delegation_chain_entry->subject_attribute,
705 del_entry->delegate->issuer_attribute))
706 continue;
707
708 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found delegate.\n");
709 // increase refcount of the start delegation
710 del_entry->refcount++;
711 }
712 // backtrack
713 for (struct DelegationSetQueueEntry *tmp_set = last_entry;
714 NULL != tmp_set->parent_queue_entry;
715 tmp_set = tmp_set->parent_queue_entry->parent_set)
716 {
717 tmp_set->parent_queue_entry->required_solutions--;
718
719 // add new found entry to vrh
720 vrh->delegation_chain_size++;
721 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
722 vrh->delegation_chain_tail,
723 tmp_set->delegation_chain_entry);
724
725 // if one node on the path still needs solutions, this current
726 // patch cannot fulfill the conditions and therefore stops here
727 // however, it is in the vrh and can be used by the other paths
728 // related to this path/collection/verification
729 if (0 < tmp_set->parent_queue_entry->required_solutions)
730 {
731 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
732 "Chain requires more solutions, waiting...\n");
733 return GNUNET_NO;
734 }
735 }
736 return GNUNET_YES;
737}
738
739
740static void
741forward_resolution (void *cls,
742 uint32_t rd_count,
743 const struct GNUNET_GNSRECORD_Data *rd)
744{
745 struct VerifyRequestHandle *vrh;
746 struct DelegationSetQueueEntry *current_set;
747 struct DelegationSetQueueEntry *ds_entry;
748 struct DelegationQueueEntry *dq_entry;
749 struct GNUNET_ABD_Delegate *del;
750
751 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d entries.\n", rd_count);
752
753 current_set = cls;
754 // set handle to NULL (as el = NULL)
755 current_set->lookup_request = NULL;
756 vrh = current_set->handle;
757 vrh->pending_lookups--;
758
759 // Loop record entries
760 for (uint32_t i = 0; i < rd_count; i++)
761 {
762 if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type)
763 continue;
764
765 // Start deserialize into Delegate
766 del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
767
768 if (NULL == del)
769 continue;
770
771 // Start: Create DQ Entry
772 dq_entry = GNUNET_new (struct DelegationQueueEntry);
773 // AND delegations are not possible, only 1 solution
774 dq_entry->required_solutions = 1;
775 dq_entry->parent_set = current_set;
776
777 // Insert it into the current set
778 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
779 current_set->queue_entries_tail,
780 dq_entry);
781
782 // Start: Create DS Entry
783 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
784 GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
785 ds_entry->from_bw = false;
786
787 // (1) A.a <- A.b.c
788 // (2) A.b <- D.d
789 // (3) D.d <- E
790 // (4) E.c <- F.c
791 // (5) F.c <- G
792 // Possibilities:
793 // 1. complete match: trailer = 0, validate
794 // 2. partial match: replace
795 // 3. new solution: replace, add trailer
796
797 // At resolution chain start trailer of parent is NULL
798 if (NULL == current_set->attr_trailer)
799 {
800 // for (5) F.c <- G, remember .c when going upwards
801 ds_entry->attr_trailer = GNUNET_strdup (del->issuer_attribute);
802 }
803 else
804 {
805 if (0 == del->subject_attribute_len)
806 {
807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: New solution\n");
808 // new solution
809 // create new trailer del->issuer_attribute, ds_entry->attr_trailer
810 GNUNET_asprintf (&ds_entry->attr_trailer,
811 "%s.%s",
812 del->issuer_attribute,
813 current_set->attr_trailer);
814 }
815 else if (0 == strcmp (del->subject_attribute, current_set->attr_trailer))
816 {
817 // complete match
818 // new trailer == issuer attribute (e.g. (5) to (4))
819 ds_entry->attr_trailer = GNUNET_strdup (del->issuer_attribute);
820 }
821 else
822 {
823 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: Partial match\n");
824 // partial match
825
826 char *trail = partial_match (GNUNET_strdup (current_set->attr_trailer),
827 GNUNET_strdup (del->subject_attribute),
828 current_set->attr_trailer,
829 GNUNET_strdup (del->issuer_attribute));
830
831 // if null: skip this record entry (reasons: mismatch or overmatch, both not relevant)
832 if (NULL == trail)
833 {
834 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
835 "Entry not relevant, discarding: %s.%s <- %s.%s\n",
836 GNUNET_IDENTITY_public_key_to_string (
837 &del->issuer_key),
838 del->issuer_attribute,
839 GNUNET_IDENTITY_public_key_to_string (
840 &del->subject_key),
841 del->subject_attribute);
842 GNUNET_free (del);
843 continue;
844 }
845 else
846 ds_entry->attr_trailer = trail;
847 }
848 }
849
850
851 // Start: Credential Chain Entry
852 // issuer key is subject key, who needs to be contacted to resolve this (forward, therefore subject)
853 ds_entry->issuer_key = GNUNET_new (struct GNUNET_IDENTITY_PublicKey);
854 GNUNET_memcpy (ds_entry->issuer_key,
855 &del->subject_key,
856 sizeof (struct GNUNET_IDENTITY_PublicKey));
857
858 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
859 ds_entry->delegation_chain_entry->subject_key = del->subject_key;
860 if (0 < del->subject_attribute_len)
861 ds_entry->delegation_chain_entry->subject_attribute =
862 GNUNET_strdup (del->subject_attribute);
863 ds_entry->delegation_chain_entry->issuer_key = del->issuer_key;
864 ds_entry->delegation_chain_entry->issuer_attribute =
865 GNUNET_strdup (del->issuer_attribute);
866
867 // Found new entry, repoting intermediate result
868 send_intermediate_response (vrh, ds_entry->delegation_chain_entry, false);
869
870 // current delegation as parent
871 ds_entry->parent_queue_entry = dq_entry;
872
873 // Check for solution
874 // if: issuer key we looking for
875 if (0 == memcmp (&del->issuer_key,
876 &vrh->issuer_key,
877 sizeof (struct GNUNET_IDENTITY_PublicKey)))
878 {
879 // if: issuer attr we looking for
880 if (0 == strcmp (del->issuer_attribute, vrh->issuer_attribute))
881 {
882 // if: complete match, meaning new trailer == issuer attr
883 if (0 == strcmp (vrh->issuer_attribute, ds_entry->attr_trailer))
884 {
885 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: Solution\n");
886
887 // Add found solution into delegation_chain
888 struct DelegationSetQueueEntry *tmp_set;
889 for (tmp_set = ds_entry; NULL != tmp_set->parent_queue_entry;
890 tmp_set = tmp_set->parent_queue_entry->parent_set)
891 {
892 if (NULL != tmp_set->delegation_chain_entry)
893 {
894 vrh->delegation_chain_size++;
895 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
896 vrh->delegation_chain_tail,
897 tmp_set->delegation_chain_entry);
898 }
899 }
900
901 // Increase refcount for this delegate
902 for (struct DelegateRecordEntry *del_entry = vrh->del_chain_head;
903 del_entry != NULL;
904 del_entry = del_entry->next)
905 {
906 if (0 == memcmp (&del_entry->delegate->issuer_key,
907 &vrh->delegation_chain_head->subject_key,
908 sizeof (struct GNUNET_IDENTITY_PublicKey)))
909 {
910 if (0 == strcmp (del_entry->delegate->issuer_attribute,
911 vrh->delegation_chain_head->subject_attribute))
912 {
913 del_entry->refcount++;
914 }
915 }
916 }
917
918 send_lookup_response (vrh);
919 GNUNET_free (del);
920 return;
921 }
922 }
923 }
924
925 // Check for bidirectional crossmatch
926 for (struct DelegationSetQueueEntry *del_entry = vrh->dsq_head;
927 del_entry != NULL;
928 del_entry = del_entry->next)
929 {
930 // only check entries not by backward algorithm
931 if (del_entry->from_bw)
932 {
933 // key of list entry matches actual key
934 if (0 == memcmp (&del_entry->delegation_chain_entry->subject_key,
935 &ds_entry->delegation_chain_entry->issuer_key,
936 sizeof (struct GNUNET_IDENTITY_PublicKey)))
937 {
938 // compare entry subject attributes to this trailer (iss attr + old trailer)
939 if (0 == strcmp (del_entry->unresolved_attribute_delegation,
940 ds_entry->attr_trailer))
941 {
942 print_deleset (del_entry, "Forward:");
943 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
944 "Forward: Found match with above!\n");
945
946 GNUNET_free (del);
947 // one node on the path still needs solutions: return
948 if (GNUNET_NO ==
949 handle_bidirectional_match (ds_entry, del_entry, vrh))
950 return;
951
952 send_lookup_response (vrh);
953 return;
954 }
955 }
956 }
957 }
958
959 // Starting a new GNS lookup
960 vrh->pending_lookups++;
961 ds_entry->handle = vrh;
962
963 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
964 "Starting to look up trailer %s in zone %s\n",
965 ds_entry->attr_trailer,
966 GNUNET_IDENTITY_public_key_to_string (&del->issuer_key));
967
968 ds_entry->lookup_request =
969 GNUNET_GNS_lookup (gns,
970 GNUNET_GNS_EMPTY_LABEL_AT,
971 &del->issuer_key,
972 GNUNET_GNSRECORD_TYPE_DELEGATE,
973 GNUNET_GNS_LO_DEFAULT,
974 &forward_resolution,
975 ds_entry);
976 GNUNET_free (del);
977 }
978
979 if (0 == vrh->pending_lookups)
980 {
981 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We are all out of attributes...\n");
982 send_lookup_response (vrh);
983 return;
984 }
985}
986
987
988static void
989backward_resolution (void *cls,
990 uint32_t rd_count,
991 const struct GNUNET_GNSRECORD_Data *rd)
992{
993 struct VerifyRequestHandle *vrh;
994 const struct GNUNET_ABD_DelegationRecord *sets;
995 struct DelegateRecordEntry *del_pointer;
996 struct DelegationSetQueueEntry *current_set;
997 struct DelegationSetQueueEntry *ds_entry;
998 struct DelegationSetQueueEntry *tmp_set;
999 struct DelegationQueueEntry *dq_entry;
1000 char *expanded_attr;
1001 char *lookup_attribute;
1002
1003 current_set = cls;
1004 current_set->lookup_request = NULL;
1005 vrh = current_set->handle;
1006 vrh->pending_lookups--;
1007
1008 // Each OR
1009 for (uint32_t i = 0; i < rd_count; i++)
1010 {
1011 if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
1012 continue;
1013
1014 sets = rd[i].data;
1015 struct GNUNET_ABD_DelegationSet set[ntohl (sets->set_count)];
1016 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1017 "Found new attribute delegation with %d sets. Creating new Job...\n",
1018 ntohl (sets->set_count));
1019
1020 if (GNUNET_OK !=
1021 GNUNET_ABD_delegation_set_deserialize (GNUNET_ntohll (
1022 sets->data_size),
1023 (const char *) &sets[1],
1024 ntohl (sets->set_count),
1025 set))
1026 {
1027 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to deserialize!\n");
1028 continue;
1029 }
1030 dq_entry = GNUNET_new (struct DelegationQueueEntry);
1031 dq_entry->required_solutions = ntohl (sets->set_count);
1032 dq_entry->parent_set = current_set;
1033
1034 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
1035 current_set->queue_entries_tail,
1036 dq_entry);
1037 // Each AND
1038 for (uint32_t j = 0; j < ntohl (sets->set_count); j++)
1039 {
1040 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
1041 GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
1042 ds_entry->from_bw = true;
1043
1044 if (NULL != current_set->attr_trailer)
1045 {
1046 if (0 == set[j].subject_attribute_len)
1047 {
1048 GNUNET_asprintf (&expanded_attr, "%s", current_set->attr_trailer);
1049 }
1050 else
1051 {
1052 GNUNET_asprintf (&expanded_attr,
1053 "%s.%s",
1054 set[j].subject_attribute,
1055 current_set->attr_trailer);
1056 }
1057 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expanded to %s\n", expanded_attr);
1058 ds_entry->unresolved_attribute_delegation = expanded_attr;
1059 }
1060 else
1061 {
1062 if (0 != set[j].subject_attribute_len)
1063 {
1064 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1065 "Not Expanding %s\n",
1066 set[j].subject_attribute);
1067 ds_entry->unresolved_attribute_delegation =
1068 GNUNET_strdup (set[j].subject_attribute);
1069 }
1070 }
1071
1072 // Add a credential chain entry
1073 ds_entry->delegation_chain_entry =
1074 GNUNET_new (struct DelegationChainEntry);
1075 ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
1076 ds_entry->issuer_key = GNUNET_new (struct GNUNET_IDENTITY_PublicKey);
1077 GNUNET_memcpy (ds_entry->issuer_key,
1078 &set[j].subject_key,
1079 sizeof (struct GNUNET_IDENTITY_PublicKey));
1080 if (0 < set[j].subject_attribute_len)
1081 ds_entry->delegation_chain_entry->subject_attribute =
1082 GNUNET_strdup (set[j].subject_attribute);
1083 ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
1084 ds_entry->delegation_chain_entry->issuer_attribute =
1085 GNUNET_strdup (current_set->lookup_attribute);
1086
1087 // Found new entry, repoting intermediate result
1088 send_intermediate_response (vrh, ds_entry->delegation_chain_entry, true);
1089
1090 ds_entry->parent_queue_entry = dq_entry; // current_delegation;
1091
1092 /**
1093 * Check if this delegation already matches one of our credentials
1094 */
1095 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking for cred match\n");
1096
1097 for (del_pointer = vrh->del_chain_head; del_pointer != NULL;
1098 del_pointer = del_pointer->next)
1099 {
1100 // If key and attribute match credential: continue and backtrack
1101 if (0 != memcmp (&set[j].subject_key,
1102 &del_pointer->delegate->issuer_key,
1103 sizeof (struct GNUNET_IDENTITY_PublicKey)))
1104 continue;
1105 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1106 "Checking if %s matches %s\n",
1107 ds_entry->unresolved_attribute_delegation,
1108 del_pointer->delegate->issuer_attribute);
1109
1110 if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
1111 del_pointer->delegate->issuer_attribute))
1112 continue;
1113
1114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found issuer\n");
1115 // increase refcount of the start delegation
1116 del_pointer->refcount++;
1117
1118 // Backtrack
1119 for (tmp_set = ds_entry; NULL != tmp_set->parent_queue_entry;
1120 tmp_set = tmp_set->parent_queue_entry->parent_set)
1121 {
1122 tmp_set->parent_queue_entry->required_solutions--;
1123 if (NULL != tmp_set->delegation_chain_entry)
1124 {
1125 vrh->delegation_chain_size++;
1126 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
1127 vrh->delegation_chain_tail,
1128 tmp_set->delegation_chain_entry);
1129 }
1130 if (0 < tmp_set->parent_queue_entry->required_solutions)
1131 break;
1132 }
1133
1134 // if the break above is not called the condition of the for is met
1135 if (NULL == tmp_set->parent_queue_entry)
1136 {
1137 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All solutions found\n");
1138 // Found match
1139 send_lookup_response (vrh);
1140 return;
1141 }
1142 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not all solutions found yet.\n");
1143 continue;
1144 }
1145
1146 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1147 "Building new lookup request from %s\n",
1148 ds_entry->unresolved_attribute_delegation);
1149 // Continue with next/new backward resolution
1150 char issuer_attribute_name[strlen (
1151 ds_entry->unresolved_attribute_delegation)
1152 + 1];
1153 strcpy (issuer_attribute_name, ds_entry->unresolved_attribute_delegation);
1154 char *next_attr = strtok (issuer_attribute_name, ".");
1155 if (NULL == next_attr)
1156 {
1157 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1158 "Failed to parse next attribute\n");
1159 continue;
1160 }
1161 GNUNET_asprintf (&lookup_attribute, "%s", next_attr);
1162 GNUNET_asprintf (&ds_entry->lookup_attribute, "%s", next_attr);
1163 if (strlen (next_attr) ==
1164 strlen (ds_entry->unresolved_attribute_delegation))
1165 {
1166 ds_entry->attr_trailer = NULL;
1167 }
1168 else
1169 {
1170 next_attr += strlen (next_attr) + 1;
1171 ds_entry->attr_trailer = GNUNET_strdup (next_attr);
1172 }
1173
1174 // Check for bidirectional crossmatch
1175 for (struct DelegationSetQueueEntry *del_entry = vrh->dsq_head;
1176 del_entry != NULL;
1177 del_entry = del_entry->next)
1178 {
1179 // only check entries added by forward algorithm
1180 if (! del_entry->from_bw)
1181 {
1182 // key of list entry matches actual key
1183 if (0 == memcmp (&del_entry->delegation_chain_entry->issuer_key,
1184 &ds_entry->delegation_chain_entry->subject_key,
1185 sizeof (struct GNUNET_IDENTITY_PublicKey)))
1186 {
1187 // compare entry subject attributes to this trailer (iss attr + old trailer)
1188 if (0 == strcmp (del_entry->attr_trailer,
1189 ds_entry->unresolved_attribute_delegation))
1190 {
1191 print_deleset (del_entry, "Backward:");
1192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1193 "Backward: Found match with above!\n");
1194
1195 // if one node on the path still needs solutions: return
1196 if (GNUNET_NO ==
1197 handle_bidirectional_match (del_entry, ds_entry, vrh))
1198 break;
1199
1200 // Send lookup response
1201 send_lookup_response (vrh);
1202 return;
1203 }
1204 }
1205 }
1206 }
1207
1208 // Starting a new GNS lookup
1209 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1210 "Looking up %s\n",
1211 ds_entry->lookup_attribute);
1212 if (NULL != ds_entry->attr_trailer)
1213 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1214 "%s still to go...\n",
1215 ds_entry->attr_trailer);
1216
1217 vrh->pending_lookups++;
1218 ds_entry->handle = vrh;
1219 ds_entry->lookup_request =
1220 GNUNET_GNS_lookup (gns,
1221 lookup_attribute,
1222 ds_entry->issuer_key, // issuer_key,
1223 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
1224 GNUNET_GNS_LO_DEFAULT,
1225 &backward_resolution,
1226 ds_entry);
1227
1228 GNUNET_free (lookup_attribute);
1229 }
1230 }
1231
1232 if (0 == vrh->pending_lookups)
1233 {
1234 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We are all out of attributes...\n");
1235 send_lookup_response (vrh);
1236 return;
1237 }
1238}
1239
1240
1241/**
1242 * Result from GNS lookup.
1243 *
1244 * @param cls the closure (our client lookup handle)
1245 */
1246static int
1247delegation_chain_bw_resolution_start (void *cls)
1248{
1249 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Start Backward Resolution...\n");
1250
1251 struct VerifyRequestHandle *vrh = cls;
1252 struct DelegationSetQueueEntry *ds_entry;
1253 struct DelegateRecordEntry *del_entry;
1254
1255 if (0 == vrh->del_chain_size)
1256 {
1257 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No delegates found\n");
1258 send_lookup_response (vrh);
1259 return 1;
1260 }
1261
1262 // Pre-check with vrh->dele_chain_.. if match issuer_key
1263 // Backward: check every cred entry if match issuer key
1264 // otherwise: start at issuer and go down till match
1265 // A.a <- ...
1266 // X.x <- C
1267 // Y.y <- C
1268 // if not X.x or Y.y == A.a start at A
1269 for (del_entry = vrh->del_chain_head; del_entry != NULL;
1270 del_entry = del_entry->next)
1271 {
1272 if (0 != memcmp (&del_entry->delegate->issuer_key,
1273 &vrh->issuer_key,
1274 sizeof (struct GNUNET_IDENTITY_PublicKey)))
1275 continue;
1276 if (0 !=
1277 strcmp (del_entry->delegate->issuer_attribute, vrh->issuer_attribute))
1278 continue;
1279 del_entry->refcount++;
1280 // Found match prematurely
1281 send_lookup_response (vrh);
1282 return 1;
1283 }
1284
1285
1286 // Check for attributes from the issuer and follow the chain
1287 // till you get the required subject's attributes
1288 char issuer_attribute_name[strlen (vrh->issuer_attribute) + 1];
1289 strcpy (issuer_attribute_name, vrh->issuer_attribute);
1290 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1291 "Looking up %s\n",
1292 issuer_attribute_name);
1293 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
1294 GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
1295 ds_entry->from_bw = true;
1296 ds_entry->issuer_key = GNUNET_new (struct GNUNET_IDENTITY_PublicKey);
1297 GNUNET_memcpy (ds_entry->issuer_key,
1298 &vrh->issuer_key,
1299 sizeof (struct GNUNET_IDENTITY_PublicKey));
1300 ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
1301
1302 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
1303 ds_entry->delegation_chain_entry->issuer_key = vrh->issuer_key;
1304 ds_entry->delegation_chain_entry->issuer_attribute =
1305 GNUNET_strdup (vrh->issuer_attribute);
1306
1307 ds_entry->handle = vrh;
1308 ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
1309 ds_entry->unresolved_attribute_delegation = NULL;
1310 vrh->pending_lookups = 1;
1311
1312 // Start with backward resolution
1313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start Backward Resolution\n");
1314
1315 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
1316 issuer_attribute_name,
1317 &vrh->issuer_key, // issuer_key,
1318 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
1319 GNUNET_GNS_LO_DEFAULT,
1320 &backward_resolution,
1321 ds_entry);
1322 return 0;
1323}
1324
1325
1326static int
1327delegation_chain_fw_resolution_start (void *cls)
1328{
1329 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Start Forward Resolution...\n");
1330
1331 struct VerifyRequestHandle *vrh = cls;
1332 struct DelegationSetQueueEntry *ds_entry;
1333 struct DelegateRecordEntry *del_entry;
1334
1335 // set to 0 and increase on each lookup: for fw multiple lookups (may be) started
1336 vrh->pending_lookups = 0;
1337
1338 if (0 == vrh->del_chain_size)
1339 {
1340 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No delegations found\n");
1341 send_lookup_response (vrh);
1342 return 1;
1343 }
1344
1345 // Pre-check with vrh->dele_chain_.. if match issuer_key
1346 // otherwise FW: start multiple lookups for each vrh->dele_chain
1347 // A.a <- ...
1348 // X.x <- C
1349 // Y.y <- C
1350 // if not X.x or Y.y == A.a start at X and at Y
1351 for (del_entry = vrh->del_chain_head; del_entry != NULL;
1352 del_entry = del_entry->next)
1353 {
1354 if (0 != memcmp (&del_entry->delegate->issuer_key,
1355 &vrh->issuer_key,
1356 sizeof (struct GNUNET_IDENTITY_PublicKey)))
1357 continue;
1358 if (0 !=
1359 strcmp (del_entry->delegate->issuer_attribute, vrh->issuer_attribute))
1360 continue;
1361 del_entry->refcount++;
1362 // Found match prematurely
1363 send_lookup_response (vrh);
1364 return 1;
1365 }
1366
1367 // None match, therefore start for every delegation found a lookup chain
1368 // Return and end collect process on first chain iss <-> sub found
1369
1370 // ds_entry created belongs to the first lookup, vrh still has the
1371 // issuer+attr we look for
1372 for (del_entry = vrh->del_chain_head; del_entry != NULL;
1373 del_entry = del_entry->next)
1374 {
1375
1376 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1377 "Looking for %s.%s\n",
1378 GNUNET_IDENTITY_public_key_to_string (
1379 &del_entry->delegate->issuer_key),
1380 del_entry->delegate->issuer_attribute);
1381
1382 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
1383 GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
1384 ds_entry->from_bw = false;
1385 ds_entry->issuer_key = GNUNET_new (struct GNUNET_IDENTITY_PublicKey);
1386 GNUNET_memcpy (ds_entry->issuer_key,
1387 &del_entry->delegate->subject_key,
1388 sizeof (struct GNUNET_IDENTITY_PublicKey));
1389
1390 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
1391 ds_entry->delegation_chain_entry->subject_key =
1392 del_entry->delegate->subject_key;
1393 ds_entry->delegation_chain_entry->subject_attribute = NULL;
1394 ds_entry->delegation_chain_entry->issuer_key =
1395 del_entry->delegate->issuer_key;
1396 ds_entry->delegation_chain_entry->issuer_attribute =
1397 GNUNET_strdup (del_entry->delegate->issuer_attribute);
1398
1399 ds_entry->attr_trailer =
1400 GNUNET_strdup (del_entry->delegate->issuer_attribute);
1401 ds_entry->handle = vrh;
1402
1403 vrh->pending_lookups++;
1404 // Start with forward resolution
1405 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start Forward Resolution\n");
1406
1407 ds_entry->lookup_request =
1408 GNUNET_GNS_lookup (gns,
1409 GNUNET_GNS_EMPTY_LABEL_AT,
1410 &del_entry->delegate->issuer_key, // issuer_key,
1411 GNUNET_GNSRECORD_TYPE_DELEGATE,
1412 GNUNET_GNS_LO_DEFAULT,
1413 &forward_resolution,
1414 ds_entry);
1415 }
1416 return 0;
1417}
1418
1419
1420static int
1421check_verify (void *cls, const struct VerifyMessage *v_msg)
1422{
1423 size_t msg_size;
1424 const char *attr;
1425
1426 msg_size = ntohs (v_msg->header.size);
1427 if (msg_size < sizeof (struct VerifyMessage))
1428 {
1429 GNUNET_break (0);
1430 return GNUNET_SYSERR;
1431 }
1432 if (ntohs (v_msg->issuer_attribute_len) > GNUNET_ABD_MAX_LENGTH)
1433 {
1434 GNUNET_break (0);
1435 return GNUNET_SYSERR;
1436 }
1437 attr = (const char *) &v_msg[1];
1438
1439 if (strlen (attr) > GNUNET_ABD_MAX_LENGTH)
1440 {
1441 GNUNET_break (0);
1442 return GNUNET_SYSERR;
1443 }
1444 return GNUNET_OK;
1445}
1446
1447
1448static void
1449handle_verify (void *cls, const struct VerifyMessage *v_msg)
1450{
1451 struct VerifyRequestHandle *vrh;
1452 struct GNUNET_SERVICE_Client *client = cls;
1453 struct DelegateRecordEntry *del_entry;
1454 uint32_t delegate_count;
1455 uint32_t delegate_data_size;
1456 char attr[GNUNET_ABD_MAX_LENGTH + 1];
1457 char issuer_attribute[GNUNET_ABD_MAX_LENGTH + 1];
1458 char *attrptr = attr;
1459 char *delegate_data;
1460 const char *utf_in;
1461
1462 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received VERIFY message\n");
1463 utf_in = (const char *) &v_msg[1];
1464 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
1465 GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
1466 issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
1467 vrh = GNUNET_new (struct VerifyRequestHandle);
1468 vrh->is_collect = false;
1469 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
1470 vrh->client = client;
1471 vrh->request_id = v_msg->id;
1472 vrh->issuer_key = v_msg->issuer_key;
1473 vrh->subject_key = v_msg->subject_key;
1474 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
1475 vrh->resolution_algo = ntohs (v_msg->resolution_algo);
1476
1477 vrh->del_chain_head = NULL;
1478 vrh->del_chain_tail = NULL;
1479 vrh->dsq_head = NULL;
1480 vrh->dsq_tail = NULL;
1481 vrh->del_chain_head = NULL;
1482 vrh->del_chain_tail = NULL;
1483
1484 GNUNET_SERVICE_client_continue (vrh->client);
1485 if (0 == strlen (issuer_attribute))
1486 {
1487 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer attribute provided!\n");
1488 send_lookup_response (vrh);
1489 return;
1490 }
1491
1492 // Parse delegates from verifaction message
1493 delegate_count = ntohl (v_msg->d_count);
1494 delegate_data_size = ntohs (v_msg->header.size)
1495 - sizeof (struct VerifyMessage)
1496 - ntohs (v_msg->issuer_attribute_len) - 1;
1497 struct GNUNET_ABD_Delegate delegates[delegate_count];
1498 memset (delegates,
1499 0,
1500 sizeof (struct GNUNET_ABD_Delegate) * delegate_count);
1501 delegate_data = (char *) &v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
1502 if (GNUNET_OK != GNUNET_ABD_delegates_deserialize (delegate_data_size,
1503 delegate_data,
1504 delegate_count,
1505 delegates))
1506 {
1507 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot deserialize delegates!\n");
1508 send_lookup_response (vrh);
1509 return;
1510 }
1511
1512 // Prepare vrh delegation chain for later validation
1513 for (uint32_t i = 0; i < delegate_count; i++)
1514 {
1515 del_entry = GNUNET_new (struct DelegateRecordEntry);
1516 del_entry->delegate =
1517 GNUNET_malloc (sizeof (struct GNUNET_ABD_Delegate)
1518 + delegates[i].issuer_attribute_len + 1);
1519 GNUNET_memcpy (del_entry->delegate,
1520 &delegates[i],
1521 sizeof (struct GNUNET_ABD_Delegate));
1522 GNUNET_memcpy (&del_entry->delegate[1],
1523 delegates[i].issuer_attribute,
1524 delegates[i].issuer_attribute_len);
1525 del_entry->delegate->issuer_attribute_len =
1526 delegates[i].issuer_attribute_len;
1527 del_entry->delegate->issuer_attribute = (char *) &del_entry->delegate[1];
1528 GNUNET_CONTAINER_DLL_insert_tail (vrh->del_chain_head,
1529 vrh->del_chain_tail,
1530 del_entry);
1531 vrh->del_chain_size++;
1532 }
1533
1534 // Switch resolution algo
1535 if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo &&
1536 GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
1537 {
1538 if (1 == delegation_chain_fw_resolution_start (vrh))
1539 return;
1540 delegation_chain_bw_resolution_start (vrh);
1541 }
1542 else if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo)
1543 {
1544 delegation_chain_bw_resolution_start (vrh);
1545 }
1546 else if (GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
1547 {
1548 delegation_chain_fw_resolution_start (vrh);
1549 }
1550}
1551
1552
1553static void
1554handle_delegate_collection_error_cb (void *cls)
1555{
1556 struct VerifyRequestHandle *vrh = cls;
1557 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1558 "Got disconnected from namestore database.\n");
1559 vrh->dele_qe = NULL;
1560 send_lookup_response (vrh);
1561}
1562
1563
1564static void
1565delegate_collection_finished (void *cls)
1566{
1567 struct VerifyRequestHandle *vrh = cls;
1568 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done collecting delegates.\n");
1569
1570 // if both are set: bidirectional search, meaning start both chain resolutions
1571 if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo &&
1572 GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
1573 {
1574 // if premature match found don't start bw resolution
1575 if (1 == delegation_chain_fw_resolution_start (vrh))
1576 return;
1577 delegation_chain_bw_resolution_start (vrh);
1578 }
1579 else if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo)
1580 {
1581 delegation_chain_bw_resolution_start (vrh);
1582 }
1583 else if (GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
1584 {
1585 delegation_chain_fw_resolution_start (vrh);
1586 }
1587}
1588
1589
1590static void
1591handle_delegate_collection_cb (void *cls,
1592 const struct GNUNET_IDENTITY_PrivateKey *key,
1593 const char *label,
1594 unsigned int rd_count,
1595 const struct GNUNET_GNSRECORD_Data *rd)
1596{
1597 struct VerifyRequestHandle *vrh = cls;
1598 struct DelegateRecordEntry *del_entry;
1599 vrh->dele_qe = NULL;
1600
1601 for (uint32_t i = 0; i < rd_count; i++)
1602 {
1603 if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type)
1604 continue;
1605 // only add the entries that are explicitly marked as private
1606 // and therefore symbolize the end of a chain
1607 if (0 == (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))
1608 continue;
1609 del_entry = GNUNET_new (struct DelegateRecordEntry);
1610 del_entry->delegate = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
1611 if (NULL == del_entry->delegate)
1612 {
1613 GNUNET_free (del_entry);
1614 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid delegate found\n");
1615 continue;
1616 }
1617 GNUNET_CONTAINER_DLL_insert_tail (vrh->del_chain_head,
1618 vrh->del_chain_tail,
1619 del_entry);
1620 vrh->del_chain_size++;
1621 }
1622
1623 delegate_collection_finished (vrh);
1624}
1625
1626
1627static void
1628handle_collect (void *cls, const struct CollectMessage *c_msg)
1629{
1630 char attr[GNUNET_ABD_MAX_LENGTH + 1];
1631 char issuer_attribute[GNUNET_ABD_MAX_LENGTH + 1];
1632 struct VerifyRequestHandle *vrh;
1633 struct GNUNET_SERVICE_Client *client = cls;
1634 char *attrptr = attr;
1635 const char *utf_in;
1636
1637 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received COLLECT message\n");
1638
1639 utf_in = (const char *) &c_msg[1];
1640 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
1641
1642 GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
1643 issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
1644 vrh = GNUNET_new (struct VerifyRequestHandle);
1645 vrh->is_collect = true;
1646 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
1647 vrh->client = client;
1648 vrh->request_id = c_msg->id;
1649 vrh->issuer_key = c_msg->issuer_key;
1650 GNUNET_IDENTITY_key_get_public (&c_msg->subject_key, &vrh->subject_key);
1651 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
1652 vrh->resolution_algo = ntohs (c_msg->resolution_algo);
1653
1654 vrh->del_chain_head = NULL;
1655 vrh->del_chain_tail = NULL;
1656 vrh->dsq_head = NULL;
1657 vrh->dsq_tail = NULL;
1658 vrh->del_chain_head = NULL;
1659 vrh->del_chain_tail = NULL;
1660
1661 if (0 == strlen (issuer_attribute))
1662 {
1663 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer attribute provided!\n");
1664 send_lookup_response (vrh);
1665 return;
1666 }
1667 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting delegates for subject\n");
1668
1669 // Get all delegates from subject
1670 vrh->dele_qe =
1671 GNUNET_NAMESTORE_records_lookup (namestore,
1672 &c_msg->subject_key,
1673 GNUNET_GNS_EMPTY_LABEL_AT,
1674 &handle_delegate_collection_error_cb,
1675 vrh,
1676 &handle_delegate_collection_cb,
1677 vrh);
1678 GNUNET_SERVICE_client_continue (vrh->client);
1679}
1680
1681
1682static int
1683check_collect (void *cls, const struct CollectMessage *c_msg)
1684{
1685 size_t msg_size;
1686 const char *attr;
1687
1688 msg_size = ntohs (c_msg->header.size);
1689 if (msg_size < sizeof (struct CollectMessage))
1690 {
1691 GNUNET_break (0);
1692 return GNUNET_SYSERR;
1693 }
1694 if (ntohs (c_msg->issuer_attribute_len) > GNUNET_ABD_MAX_LENGTH)
1695 {
1696 GNUNET_break (0);
1697 return GNUNET_SYSERR;
1698 }
1699 attr = (const char *) &c_msg[1];
1700
1701 if (('\0' != attr[msg_size - sizeof (struct CollectMessage) - 1]) ||
1702 (strlen (attr) > GNUNET_ABD_MAX_LENGTH))
1703 {
1704 GNUNET_break (0);
1705 return GNUNET_SYSERR;
1706 }
1707 return GNUNET_OK;
1708}
1709
1710
1711static void
1712client_disconnect_cb (void *cls,
1713 struct GNUNET_SERVICE_Client *client,
1714 void *app_ctx)
1715{
1716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1717}
1718
1719
1720static void *
1721client_connect_cb (void *cls,
1722 struct GNUNET_SERVICE_Client *client,
1723 struct GNUNET_MQ_Handle *mq)
1724{
1725 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1726 return client;
1727}
1728
1729
1730/**
1731 * Process Credential requests.
1732 *
1733 * @param cls closure
1734 * @param c configuration to use
1735 * @param handle service handle
1736 */
1737static void
1738run (void *cls,
1739 const struct GNUNET_CONFIGURATION_Handle *c,
1740 struct GNUNET_SERVICE_Handle *handle)
1741{
1742
1743 gns = GNUNET_GNS_connect (c);
1744 if (NULL == gns)
1745 {
1746 fprintf (stderr, _ ("Failed to connect to GNS\n"));
1747 }
1748 namestore = GNUNET_NAMESTORE_connect (c);
1749 if (NULL == namestore)
1750 {
1751 fprintf (stderr, _ ("Failed to connect to namestore\n"));
1752 }
1753
1754 statistics = GNUNET_STATISTICS_create ("abd", c);
1755 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1756}
1757
1758
1759/**
1760 * Define "main" method using service macro
1761 */
1762GNUNET_SERVICE_MAIN (
1763 "abd",
1764 GNUNET_SERVICE_OPTION_NONE,
1765 &run,
1766 &client_connect_cb,
1767 &client_disconnect_cb,
1768 NULL,
1769 GNUNET_MQ_hd_var_size (verify,
1770 GNUNET_MESSAGE_TYPE_ABD_VERIFY,
1771 struct VerifyMessage,
1772 NULL),
1773 GNUNET_MQ_hd_var_size (collect,
1774 GNUNET_MESSAGE_TYPE_ABD_COLLECT,
1775 struct CollectMessage,
1776 NULL),
1777 GNUNET_MQ_handler_end ());
1778
1779/* end of gnunet-service-abd.c */