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