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.c1775
1 files changed, 0 insertions, 1775 deletions
diff --git a/src/abd/gnunet-service-abd.c b/src/abd/gnunet-service-abd.c
deleted file mode 100644
index 93368da45..000000000
--- a/src/abd/gnunet-service-abd.c
+++ /dev/null
@@ -1,1775 +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_CRYPTO_EcdsaPublicKey issuer_key;
65
66 /**
67 * The subject
68 */
69 struct GNUNET_CRYPTO_EcdsaPublicKey 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_CRYPTO_EcdsaPublicKey *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_CRYPTO_EcdsaPublicKey issuer_key;
271
272 /**
273 * Issuer attribute
274 */
275 char *issuer_attribute;
276
277 /**
278 * Subject public key
279 */
280 struct GNUNET_CRYPTO_EcdsaPublicKey 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_CRYPTO_ecdsa_public_key_to_string (
356 &dsentry->delegation_chain_entry->issuer_key),
357 dsentry->delegation_chain_entry->issuer_attribute,
358 GNUNET_CRYPTO_ecdsa_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
517
518static void
519send_lookup_response (struct VerifyRequestHandle *vrh)
520{
521 struct GNUNET_MQ_Envelope *env;
522 struct DelegationChainResultMessage *rmsg;
523 struct DelegationChainEntry *dce;
524 struct GNUNET_ABD_Delegation dd[vrh->delegation_chain_size];
525 struct GNUNET_ABD_Delegate dele[vrh->del_chain_size];
526 struct DelegateRecordEntry *del;
527 struct DelegateRecordEntry *tmp;
528 size_t size;
529
530 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending response\n");
531 dce = vrh->delegation_chain_head;
532 for (uint32_t i = 0; i < vrh->delegation_chain_size; i++)
533 {
534 dd[i].issuer_key = dce->issuer_key;
535 dd[i].subject_key = dce->subject_key;
536 dd[i].issuer_attribute = dce->issuer_attribute;
537 dd[i].issuer_attribute_len = strlen (dce->issuer_attribute) + 1;
538 dd[i].subject_attribute_len = 0;
539 dd[i].subject_attribute = NULL;
540 if (NULL != dce->subject_attribute)
541 {
542 dd[i].subject_attribute = dce->subject_attribute;
543 dd[i].subject_attribute_len = strlen (dce->subject_attribute) + 1;
544 }
545 dce = dce->next;
546 }
547
548 // Remove all not needed credentials
549 for (del = vrh->del_chain_head; NULL != del;)
550 {
551 if (del->refcount > 0)
552 {
553 del = del->next;
554 continue;
555 }
556 tmp = del;
557 del = del->next;
558 GNUNET_CONTAINER_DLL_remove (vrh->del_chain_head, vrh->del_chain_tail, tmp);
559 GNUNET_free (tmp->delegate);
560 GNUNET_free (tmp);
561 vrh->del_chain_size--;
562 }
563
564 // Get serialized record data
565 // Append at the end of rmsg
566 del = vrh->del_chain_head;
567 for (uint32_t i = 0; i < vrh->del_chain_size; i++)
568 {
569 dele[i].issuer_key = del->delegate->issuer_key;
570 dele[i].subject_key = del->delegate->subject_key;
571 dele[i].issuer_attribute_len = strlen (del->delegate->issuer_attribute) + 1;
572 dele[i].issuer_attribute = del->delegate->issuer_attribute;
573 dele[i].subject_attribute_len = del->delegate->subject_attribute_len;
574 dele[i].subject_attribute = del->delegate->subject_attribute;
575 dele[i].expiration = del->delegate->expiration;
576 dele[i].signature = del->delegate->signature;
577 del = del->next;
578 }
579 size =
580 GNUNET_ABD_delegation_chain_get_size (vrh->delegation_chain_size,
581 dd,
582 vrh->del_chain_size,
583 dele);
584 env = GNUNET_MQ_msg_extra (rmsg,
585 size,
586 GNUNET_MESSAGE_TYPE_ABD_VERIFY_RESULT);
587 // Assign id so that client can find associated request
588 rmsg->id = vrh->request_id;
589 rmsg->d_count = htonl (vrh->delegation_chain_size);
590 rmsg->c_count = htonl (vrh->del_chain_size);
591
592 if (0 < vrh->del_chain_size)
593 rmsg->del_found = htonl (GNUNET_YES);
594 else
595 rmsg->del_found = htonl (GNUNET_NO);
596
597 GNUNET_assert (
598 -1 !=
599 GNUNET_ABD_delegation_chain_serialize (vrh->delegation_chain_size,
600 dd,
601 vrh->del_chain_size,
602 dele,
603 size,
604 (char *) &rmsg[1]));
605
606 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (vrh->client), env);
607 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
608 cleanup_handle (vrh);
609 GNUNET_STATISTICS_update (statistics,
610 "Completed verifications",
611 1,
612 GNUNET_NO);
613}
614
615
616static char *
617partial_match (char *tmp_trail,
618 char *tmp_subattr,
619 char *parent_trail,
620 char *issuer_attribute)
621{
622 char *saveptr1, *saveptr2;
623 char *trail_token;
624 char *sub_token;
625 char *attr_trailer;
626
627 // tok both, parent->attr_trailer and del->sub_attr to see how far they match,
628 // take rest of parent trailer (only when del->sub_attr token is null), and
629 // create new/actual trailer with del->iss_attr
630 trail_token = strtok_r (tmp_trail, ".", &saveptr1);
631 sub_token = strtok_r (tmp_subattr, ".", &saveptr2);
632 while (NULL != trail_token && NULL != sub_token)
633 {
634 if (0 == strcmp (trail_token, sub_token))
635 {
636 // good, matches, remove
637 }
638 else
639 {
640 // not relevant for solving the chain, end for iteration here
641 return NULL;
642 }
643
644 trail_token = strtok_r (NULL, ".", &saveptr1);
645 sub_token = strtok_r (NULL, ".", &saveptr2);
646 }
647 // skip this entry and go to next for if:
648 // 1. at some point the attr of the trailer and the subject dont match
649 // 2. the trailer is NULL, but the subject has more attributes
650 // Reason: This will lead to "startzone.attribute" but we're looking for a solution
651 // for "<- startzone"
652 if (NULL == trail_token)
653 {
654 return NULL;
655 }
656
657 // do not have to check sub_token == NULL, if both would be NULL
658 // at the same time, the complete match part above should have triggered already
659
660 // otherwise, above while only ends when sub_token == NULL
661 GNUNET_asprintf (&attr_trailer, "%s", trail_token);
662 trail_token = strtok_r (NULL, ".", &saveptr1);
663 while (NULL != trail_token)
664 {
665 GNUNET_asprintf (&attr_trailer, "%s.%s", parent_trail, trail_token);
666 trail_token = strtok_r (NULL, ".", &saveptr1);
667 }
668 GNUNET_asprintf (&attr_trailer, "%s.%s", issuer_attribute, attr_trailer);
669 return attr_trailer;
670}
671
672
673static int
674handle_bidirectional_match (struct DelegationSetQueueEntry *actual_entry,
675 struct DelegationSetQueueEntry *match_entry,
676 struct VerifyRequestHandle *vrh)
677{
678 struct DelegationSetQueueEntry *old_fw_parent;
679 struct DelegationSetQueueEntry *fw_entry = actual_entry;
680 struct DelegationSetQueueEntry *last_entry = match_entry;
681 // parent fixing, combine backward and forward chain parts
682 while (NULL != fw_entry->parent_queue_entry)
683 {
684 old_fw_parent = fw_entry->parent_queue_entry->parent_set;
685 // set parent
686 fw_entry->parent_queue_entry->parent_set = last_entry;
687
688 last_entry = fw_entry;
689 fw_entry = old_fw_parent;
690 }
691 // set last entry of chain as actual_entry
692 // actual_entry = last_entry;
693 // set refcount, loop all delegations
694 for (struct DelegateRecordEntry *del_entry = vrh->del_chain_head;
695 del_entry != NULL;
696 del_entry = del_entry->next)
697 {
698 if (0 != memcmp (&last_entry->delegation_chain_entry->subject_key,
699 &del_entry->delegate->issuer_key,
700 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
701 continue;
702 if (0 != strcmp (last_entry->delegation_chain_entry->subject_attribute,
703 del_entry->delegate->issuer_attribute))
704 continue;
705
706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found delegate.\n");
707 // increase refcount of the start delegation
708 del_entry->refcount++;
709 }
710 // backtrack
711 for (struct DelegationSetQueueEntry *tmp_set = last_entry;
712 NULL != tmp_set->parent_queue_entry;
713 tmp_set = tmp_set->parent_queue_entry->parent_set)
714 {
715 tmp_set->parent_queue_entry->required_solutions--;
716
717 // add new found entry to vrh
718 vrh->delegation_chain_size++;
719 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
720 vrh->delegation_chain_tail,
721 tmp_set->delegation_chain_entry);
722
723 // if one node on the path still needs solutions, this current
724 // patch cannot fulfill the conditions and therefore stops here
725 // however, it is in the vrh and can be used by the other paths
726 // related to this path/collection/verification
727 if (0 < tmp_set->parent_queue_entry->required_solutions)
728 {
729 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
730 "Chain requires more solutions, waiting...\n");
731 return GNUNET_NO;
732 }
733 }
734 return GNUNET_YES;
735}
736
737
738static void
739forward_resolution (void *cls,
740 uint32_t rd_count,
741 const struct GNUNET_GNSRECORD_Data *rd)
742{
743 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d entries.\n", rd_count);
744
745 struct VerifyRequestHandle *vrh;
746 struct DelegationSetQueueEntry *current_set;
747 struct DelegationSetQueueEntry *ds_entry;
748 struct DelegationQueueEntry *dq_entry;
749
750 current_set = cls;
751 // set handle to NULL (as el = NULL)
752 current_set->lookup_request = NULL;
753 vrh = current_set->handle;
754 vrh->pending_lookups--;
755
756 // Loop record entries
757 for (uint32_t i = 0; i < rd_count; i++)
758 {
759 if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type)
760 continue;
761
762 // Start deserialize into Delegate
763 struct GNUNET_ABD_Delegate *del;
764 del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
765
766 // Start: Create DQ Entry
767 dq_entry = GNUNET_new (struct DelegationQueueEntry);
768 // AND delegations are not possible, only 1 solution
769 dq_entry->required_solutions = 1;
770 dq_entry->parent_set = current_set;
771
772 // Insert it into the current set
773 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
774 current_set->queue_entries_tail,
775 dq_entry);
776
777 // Start: Create DS Entry
778 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
779 GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
780 ds_entry->from_bw = false;
781
782 // (1) A.a <- A.b.c
783 // (2) A.b <- D.d
784 // (3) D.d <- E
785 // (4) E.c <- F.c
786 // (5) F.c <- G
787 // Possibilities:
788 // 1. complete match: trailer = 0, validate
789 // 2. partial match: replace
790 // 3. new solution: replace, add trailer
791
792 // At resolution chain start trailer of parent is NULL
793 if (NULL == current_set->attr_trailer)
794 {
795 // for (5) F.c <- G, remember .c when going upwards
796 ds_entry->attr_trailer = GNUNET_strdup (del->issuer_attribute);
797 }
798 else
799 {
800 if (0 == del->subject_attribute_len)
801 {
802 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: New solution\n");
803 // new solution
804 // create new trailer del->issuer_attribute, ds_entry->attr_trailer
805 GNUNET_asprintf (&ds_entry->attr_trailer,
806 "%s.%s",
807 del->issuer_attribute,
808 current_set->attr_trailer);
809 }
810 else if (0 == strcmp (del->subject_attribute, current_set->attr_trailer))
811 {
812 // complete match
813 // new trailer == issuer attribute (e.g. (5) to (4))
814 ds_entry->attr_trailer = GNUNET_strdup (del->issuer_attribute);
815 }
816 else
817 {
818 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: Partial match\n");
819 // partial match
820
821 char *trail = partial_match (GNUNET_strdup (current_set->attr_trailer),
822 GNUNET_strdup (del->subject_attribute),
823 current_set->attr_trailer,
824 GNUNET_strdup (del->issuer_attribute));
825
826 // if null: skip this record entry (reasons: mismatch or overmatch, both not relevant)
827 if (NULL == trail)
828 {
829 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
830 "Entry not relevant, discarding: %s.%s <- %s.%s\n",
831 GNUNET_CRYPTO_ecdsa_public_key_to_string (
832 &del->issuer_key),
833 del->issuer_attribute,
834 GNUNET_CRYPTO_ecdsa_public_key_to_string (
835 &del->subject_key),
836 del->subject_attribute);
837 continue;
838 }
839 else
840 ds_entry->attr_trailer = trail;
841 }
842 }
843
844
845 // Start: Credential Chain Entry
846 // issuer key is subject key, who needs to be contacted to resolve this (forward, therefore subject)
847 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
848 GNUNET_memcpy (ds_entry->issuer_key,
849 &del->subject_key,
850 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
851
852 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
853 ds_entry->delegation_chain_entry->subject_key = del->subject_key;
854 if (0 < del->subject_attribute_len)
855 ds_entry->delegation_chain_entry->subject_attribute =
856 GNUNET_strdup (del->subject_attribute);
857 ds_entry->delegation_chain_entry->issuer_key = del->issuer_key;
858 ds_entry->delegation_chain_entry->issuer_attribute =
859 GNUNET_strdup (del->issuer_attribute);
860
861 // Found new entry, repoting intermediate result
862 send_intermediate_response (vrh, ds_entry->delegation_chain_entry, false);
863
864 // current delegation as parent
865 ds_entry->parent_queue_entry = dq_entry;
866
867 // Check for solution
868 // if: issuer key we looking for
869 if (0 == memcmp (&del->issuer_key,
870 &vrh->issuer_key,
871 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
872 {
873 // if: issuer attr we looking for
874 if (0 == strcmp (del->issuer_attribute, vrh->issuer_attribute))
875 {
876 // if: complete match, meaning new trailer == issuer attr
877 if (0 == strcmp (vrh->issuer_attribute, ds_entry->attr_trailer))
878 {
879 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: Solution\n");
880
881 // Add found solution into delegation_chain
882 struct DelegationSetQueueEntry *tmp_set;
883 for (tmp_set = ds_entry; NULL != tmp_set->parent_queue_entry;
884 tmp_set = tmp_set->parent_queue_entry->parent_set)
885 {
886 if (NULL != tmp_set->delegation_chain_entry)
887 {
888 vrh->delegation_chain_size++;
889 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
890 vrh->delegation_chain_tail,
891 tmp_set->delegation_chain_entry);
892 }
893 }
894
895 // Increase refcount for this delegate
896 for (struct DelegateRecordEntry *del_entry = vrh->del_chain_head;
897 del_entry != NULL;
898 del_entry = del_entry->next)
899 {
900 if (0 == memcmp (&del_entry->delegate->issuer_key,
901 &vrh->delegation_chain_head->subject_key,
902 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
903 {
904 if (0 == strcmp (del_entry->delegate->issuer_attribute,
905 vrh->delegation_chain_head->subject_attribute))
906 {
907 del_entry->refcount++;
908 }
909 }
910 }
911
912 send_lookup_response (vrh);
913 return;
914 }
915 }
916 }
917
918 // Check for bidirectional crossmatch
919 for (struct DelegationSetQueueEntry *del_entry = vrh->dsq_head;
920 del_entry != NULL;
921 del_entry = del_entry->next)
922 {
923 // only check entries not by backward algorithm
924 if (del_entry->from_bw)
925 {
926 // key of list entry matches actual key
927 if (0 == memcmp (&del_entry->delegation_chain_entry->subject_key,
928 &ds_entry->delegation_chain_entry->issuer_key,
929 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
930 {
931 // compare entry subject attributes to this trailer (iss attr + old trailer)
932 if (0 == strcmp (del_entry->unresolved_attribute_delegation,
933 ds_entry->attr_trailer))
934 {
935 print_deleset (del_entry, "Forward:");
936 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
937 "Forward: Found match with above!\n");
938
939 // one node on the path still needs solutions: return
940 if (GNUNET_NO ==
941 handle_bidirectional_match (ds_entry, del_entry, vrh))
942 return;
943
944 send_lookup_response (vrh);
945 return;
946 }
947 }
948 }
949 }
950
951 // Starting a new GNS lookup
952 vrh->pending_lookups++;
953 ds_entry->handle = vrh;
954
955 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
956 "Starting to look up trailer %s in zone %s\n",
957 ds_entry->attr_trailer,
958 GNUNET_CRYPTO_ecdsa_public_key_to_string (&del->issuer_key));
959
960 ds_entry->lookup_request =
961 GNUNET_GNS_lookup (gns,
962 GNUNET_GNS_EMPTY_LABEL_AT,
963 &del->issuer_key,
964 GNUNET_GNSRECORD_TYPE_DELEGATE,
965 GNUNET_GNS_LO_DEFAULT,
966 &forward_resolution,
967 ds_entry);
968 }
969
970 if (0 == vrh->pending_lookups)
971 {
972 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We are all out of attributes...\n");
973 send_lookup_response (vrh);
974 return;
975 }
976}
977
978
979static void
980backward_resolution (void *cls,
981 uint32_t rd_count,
982 const struct GNUNET_GNSRECORD_Data *rd)
983{
984 struct VerifyRequestHandle *vrh;
985 const struct GNUNET_ABD_DelegationRecord *sets;
986 struct DelegateRecordEntry *del_pointer;
987 struct DelegationSetQueueEntry *current_set;
988 struct DelegationSetQueueEntry *ds_entry;
989 struct DelegationSetQueueEntry *tmp_set;
990 struct DelegationQueueEntry *dq_entry;
991 char *expanded_attr;
992 char *lookup_attribute;
993
994 current_set = cls;
995 current_set->lookup_request = NULL;
996 vrh = current_set->handle;
997 vrh->pending_lookups--;
998
999 // Each OR
1000 for (uint32_t i = 0; i < rd_count; i++)
1001 {
1002 if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
1003 continue;
1004
1005 sets = rd[i].data;
1006 struct GNUNET_ABD_DelegationSet set[ntohl (sets->set_count)];
1007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1008 "Found new attribute delegation with %d sets. Creating new Job...\n",
1009 ntohl (sets->set_count));
1010
1011 if (GNUNET_OK !=
1012 GNUNET_ABD_delegation_set_deserialize (GNUNET_ntohll (
1013 sets->data_size),
1014 (const char *) &sets[1],
1015 ntohl (sets->set_count),
1016 set))
1017 {
1018 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to deserialize!\n");
1019 continue;
1020 }
1021 dq_entry = GNUNET_new (struct DelegationQueueEntry);
1022 dq_entry->required_solutions = ntohl (sets->set_count);
1023 dq_entry->parent_set = current_set;
1024
1025 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
1026 current_set->queue_entries_tail,
1027 dq_entry);
1028 // Each AND
1029 for (uint32_t j = 0; j < ntohl (sets->set_count); j++)
1030 {
1031 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
1032 GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
1033 ds_entry->from_bw = true;
1034
1035 if (NULL != current_set->attr_trailer)
1036 {
1037 if (0 == set[j].subject_attribute_len)
1038 {
1039 GNUNET_asprintf (&expanded_attr, "%s", current_set->attr_trailer);
1040 }
1041 else
1042 {
1043 GNUNET_asprintf (&expanded_attr,
1044 "%s.%s",
1045 set[j].subject_attribute,
1046 current_set->attr_trailer);
1047 }
1048 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expanded to %s\n", expanded_attr);
1049 ds_entry->unresolved_attribute_delegation = expanded_attr;
1050 }
1051 else
1052 {
1053 if (0 != set[j].subject_attribute_len)
1054 {
1055 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1056 "Not Expanding %s\n",
1057 set[j].subject_attribute);
1058 ds_entry->unresolved_attribute_delegation =
1059 GNUNET_strdup (set[j].subject_attribute);
1060 }
1061 }
1062
1063 // Add a credential chain entry
1064 ds_entry->delegation_chain_entry =
1065 GNUNET_new (struct DelegationChainEntry);
1066 ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
1067 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
1068 GNUNET_memcpy (ds_entry->issuer_key,
1069 &set[j].subject_key,
1070 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1071 if (0 < set[j].subject_attribute_len)
1072 ds_entry->delegation_chain_entry->subject_attribute =
1073 GNUNET_strdup (set[j].subject_attribute);
1074 ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
1075 ds_entry->delegation_chain_entry->issuer_attribute =
1076 GNUNET_strdup (current_set->lookup_attribute);
1077
1078 // Found new entry, repoting intermediate result
1079 send_intermediate_response (vrh, ds_entry->delegation_chain_entry, true);
1080
1081 ds_entry->parent_queue_entry = dq_entry; // current_delegation;
1082
1083 /**
1084 * Check if this delegation already matches one of our credentials
1085 */
1086 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking for cred match\n");
1087
1088 for (del_pointer = vrh->del_chain_head; del_pointer != NULL;
1089 del_pointer = del_pointer->next)
1090 {
1091 // If key and attribute match credential: continue and backtrack
1092 if (0 != memcmp (&set[j].subject_key,
1093 &del_pointer->delegate->issuer_key,
1094 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
1095 continue;
1096 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1097 "Checking if %s matches %s\n",
1098 ds_entry->unresolved_attribute_delegation,
1099 del_pointer->delegate->issuer_attribute);
1100
1101 if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
1102 del_pointer->delegate->issuer_attribute))
1103 continue;
1104
1105 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found issuer\n");
1106 // increase refcount of the start delegation
1107 del_pointer->refcount++;
1108
1109 // Backtrack
1110 for (tmp_set = ds_entry; NULL != tmp_set->parent_queue_entry;
1111 tmp_set = tmp_set->parent_queue_entry->parent_set)
1112 {
1113 tmp_set->parent_queue_entry->required_solutions--;
1114 if (NULL != tmp_set->delegation_chain_entry)
1115 {
1116 vrh->delegation_chain_size++;
1117 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
1118 vrh->delegation_chain_tail,
1119 tmp_set->delegation_chain_entry);
1120 }
1121 if (0 < tmp_set->parent_queue_entry->required_solutions)
1122 break;
1123 }
1124
1125 // if the break above is not called the condition of the for is met
1126 if (NULL == tmp_set->parent_queue_entry)
1127 {
1128 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All solutions found\n");
1129 // Found match
1130 send_lookup_response (vrh);
1131 return;
1132 }
1133 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not all solutions found yet.\n");
1134 continue;
1135 }
1136
1137 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1138 "Building new lookup request from %s\n",
1139 ds_entry->unresolved_attribute_delegation);
1140 // Continue with next/new backward resolution
1141 char issuer_attribute_name[strlen (
1142 ds_entry->unresolved_attribute_delegation)
1143 + 1];
1144 strcpy (issuer_attribute_name, ds_entry->unresolved_attribute_delegation);
1145 char *next_attr = strtok (issuer_attribute_name, ".");
1146 if (NULL == next_attr)
1147 {
1148 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1149 "Failed to parse next attribute\n");
1150 continue;
1151 }
1152 GNUNET_asprintf (&lookup_attribute, "%s", next_attr);
1153 GNUNET_asprintf (&ds_entry->lookup_attribute, "%s", next_attr);
1154 if (strlen (next_attr) ==
1155 strlen (ds_entry->unresolved_attribute_delegation))
1156 {
1157 ds_entry->attr_trailer = NULL;
1158 }
1159 else
1160 {
1161 next_attr += strlen (next_attr) + 1;
1162 ds_entry->attr_trailer = GNUNET_strdup (next_attr);
1163 }
1164
1165 // Check for bidirectional crossmatch
1166 for (struct DelegationSetQueueEntry *del_entry = vrh->dsq_head;
1167 del_entry != NULL;
1168 del_entry = del_entry->next)
1169 {
1170 // only check entries added by forward algorithm
1171 if (! del_entry->from_bw)
1172 {
1173 // key of list entry matches actual key
1174 if (0 == memcmp (&del_entry->delegation_chain_entry->issuer_key,
1175 &ds_entry->delegation_chain_entry->subject_key,
1176 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
1177 {
1178 // compare entry subject attributes to this trailer (iss attr + old trailer)
1179 if (0 == strcmp (del_entry->attr_trailer,
1180 ds_entry->unresolved_attribute_delegation))
1181 {
1182 print_deleset (del_entry, "Backward:");
1183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1184 "Backward: Found match with above!\n");
1185
1186 // if one node on the path still needs solutions: return
1187 if (GNUNET_NO ==
1188 handle_bidirectional_match (del_entry, ds_entry, vrh))
1189 break;
1190
1191 // Send lookup response
1192 send_lookup_response (vrh);
1193 return;
1194 }
1195 }
1196 }
1197 }
1198
1199 // Starting a new GNS lookup
1200 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1201 "Looking up %s\n",
1202 ds_entry->lookup_attribute);
1203 if (NULL != ds_entry->attr_trailer)
1204 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1205 "%s still to go...\n",
1206 ds_entry->attr_trailer);
1207
1208 vrh->pending_lookups++;
1209 ds_entry->handle = vrh;
1210 ds_entry->lookup_request =
1211 GNUNET_GNS_lookup (gns,
1212 lookup_attribute,
1213 ds_entry->issuer_key, // issuer_key,
1214 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
1215 GNUNET_GNS_LO_DEFAULT,
1216 &backward_resolution,
1217 ds_entry);
1218
1219 GNUNET_free (lookup_attribute);
1220 }
1221 }
1222
1223 if (0 == vrh->pending_lookups)
1224 {
1225 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We are all out of attributes...\n");
1226 send_lookup_response (vrh);
1227 return;
1228 }
1229}
1230
1231
1232/**
1233 * Result from GNS lookup.
1234 *
1235 * @param cls the closure (our client lookup handle)
1236 */
1237static int
1238delegation_chain_bw_resolution_start (void *cls)
1239{
1240 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Start Backward Resolution...\n");
1241
1242 struct VerifyRequestHandle *vrh = cls;
1243 struct DelegationSetQueueEntry *ds_entry;
1244 struct DelegateRecordEntry *del_entry;
1245
1246 if (0 == vrh->del_chain_size)
1247 {
1248 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No delegates found\n");
1249 send_lookup_response (vrh);
1250 return 1;
1251 }
1252
1253 // Pre-check with vrh->dele_chain_.. if match issuer_key
1254 // Backward: check every cred entry if match issuer key
1255 // otherwise: start at issuer and go down till match
1256 // A.a <- ...
1257 // X.x <- C
1258 // Y.y <- C
1259 // if not X.x or Y.y == A.a start at A
1260 for (del_entry = vrh->del_chain_head; del_entry != NULL;
1261 del_entry = del_entry->next)
1262 {
1263 if (0 != memcmp (&del_entry->delegate->issuer_key,
1264 &vrh->issuer_key,
1265 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
1266 continue;
1267 if (0 !=
1268 strcmp (del_entry->delegate->issuer_attribute, vrh->issuer_attribute))
1269 continue;
1270 del_entry->refcount++;
1271 // Found match prematurely
1272 send_lookup_response (vrh);
1273 return 1;
1274 }
1275
1276
1277 // Check for attributes from the issuer and follow the chain
1278 // till you get the required subject's attributes
1279 char issuer_attribute_name[strlen (vrh->issuer_attribute) + 1];
1280 strcpy (issuer_attribute_name, vrh->issuer_attribute);
1281 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1282 "Looking up %s\n",
1283 issuer_attribute_name);
1284 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
1285 GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
1286 ds_entry->from_bw = true;
1287 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
1288 GNUNET_memcpy (ds_entry->issuer_key,
1289 &vrh->issuer_key,
1290 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1291 ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
1292
1293 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
1294 ds_entry->delegation_chain_entry->issuer_key = vrh->issuer_key;
1295 ds_entry->delegation_chain_entry->issuer_attribute =
1296 GNUNET_strdup (vrh->issuer_attribute);
1297
1298 ds_entry->handle = vrh;
1299 ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
1300 ds_entry->unresolved_attribute_delegation = NULL;
1301 vrh->pending_lookups = 1;
1302
1303 // Start with backward resolution
1304 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start Backward Resolution\n");
1305
1306 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
1307 issuer_attribute_name,
1308 &vrh->issuer_key, // issuer_key,
1309 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
1310 GNUNET_GNS_LO_DEFAULT,
1311 &backward_resolution,
1312 ds_entry);
1313 return 0;
1314}
1315
1316
1317static int
1318delegation_chain_fw_resolution_start (void *cls)
1319{
1320 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Start Forward Resolution...\n");
1321
1322 struct VerifyRequestHandle *vrh = cls;
1323 struct DelegationSetQueueEntry *ds_entry;
1324 struct DelegateRecordEntry *del_entry;
1325
1326 // set to 0 and increase on each lookup: for fw multiple lookups (may be) started
1327 vrh->pending_lookups = 0;
1328
1329 if (0 == vrh->del_chain_size)
1330 {
1331 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No delegations found\n");
1332 send_lookup_response (vrh);
1333 return 1;
1334 }
1335
1336 // Pre-check with vrh->dele_chain_.. if match issuer_key
1337 // otherwise FW: start multiple lookups for each vrh->dele_chain
1338 // A.a <- ...
1339 // X.x <- C
1340 // Y.y <- C
1341 // if not X.x or Y.y == A.a start at X and at Y
1342 for (del_entry = vrh->del_chain_head; del_entry != NULL;
1343 del_entry = del_entry->next)
1344 {
1345 if (0 != memcmp (&del_entry->delegate->issuer_key,
1346 &vrh->issuer_key,
1347 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
1348 continue;
1349 if (0 !=
1350 strcmp (del_entry->delegate->issuer_attribute, vrh->issuer_attribute))
1351 continue;
1352 del_entry->refcount++;
1353 // Found match prematurely
1354 send_lookup_response (vrh);
1355 return 1;
1356 }
1357
1358 // None match, therefore start for every delegation found a lookup chain
1359 // Return and end collect process on first chain iss <-> sub found
1360
1361 // ds_entry created belongs to the first lookup, vrh still has the
1362 // issuer+attr we look for
1363 for (del_entry = vrh->del_chain_head; del_entry != NULL;
1364 del_entry = del_entry->next)
1365 {
1366
1367 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1368 "Looking for %s.%s\n",
1369 GNUNET_CRYPTO_ecdsa_public_key_to_string (
1370 &del_entry->delegate->issuer_key),
1371 del_entry->delegate->issuer_attribute);
1372
1373 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
1374 GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
1375 ds_entry->from_bw = false;
1376 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
1377 GNUNET_memcpy (ds_entry->issuer_key,
1378 &del_entry->delegate->subject_key,
1379 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1380
1381 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
1382 ds_entry->delegation_chain_entry->subject_key =
1383 del_entry->delegate->subject_key;
1384 ds_entry->delegation_chain_entry->subject_attribute = NULL;
1385 ds_entry->delegation_chain_entry->issuer_key =
1386 del_entry->delegate->issuer_key;
1387 ds_entry->delegation_chain_entry->issuer_attribute =
1388 GNUNET_strdup (del_entry->delegate->issuer_attribute);
1389
1390 ds_entry->attr_trailer =
1391 GNUNET_strdup (del_entry->delegate->issuer_attribute);
1392 ds_entry->handle = vrh;
1393
1394 vrh->pending_lookups++;
1395 // Start with forward resolution
1396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start Forward Resolution\n");
1397
1398 ds_entry->lookup_request =
1399 GNUNET_GNS_lookup (gns,
1400 GNUNET_GNS_EMPTY_LABEL_AT,
1401 &del_entry->delegate->issuer_key, // issuer_key,
1402 GNUNET_GNSRECORD_TYPE_DELEGATE,
1403 GNUNET_GNS_LO_DEFAULT,
1404 &forward_resolution,
1405 ds_entry);
1406 }
1407 return 0;
1408}
1409
1410
1411static int
1412check_verify (void *cls, const struct VerifyMessage *v_msg)
1413{
1414 size_t msg_size;
1415 const char *attr;
1416
1417 msg_size = ntohs (v_msg->header.size);
1418 if (msg_size < sizeof (struct VerifyMessage))
1419 {
1420 GNUNET_break (0);
1421 return GNUNET_SYSERR;
1422 }
1423 if (ntohs (v_msg->issuer_attribute_len) > GNUNET_ABD_MAX_LENGTH)
1424 {
1425 GNUNET_break (0);
1426 return GNUNET_SYSERR;
1427 }
1428 attr = (const char *) &v_msg[1];
1429
1430 if (strlen (attr) > GNUNET_ABD_MAX_LENGTH)
1431 {
1432 GNUNET_break (0);
1433 return GNUNET_SYSERR;
1434 }
1435 return GNUNET_OK;
1436}
1437
1438
1439static void
1440handle_verify (void *cls, const struct VerifyMessage *v_msg)
1441{
1442 struct VerifyRequestHandle *vrh;
1443 struct GNUNET_SERVICE_Client *client = cls;
1444 struct DelegateRecordEntry *del_entry;
1445 uint32_t delegate_count;
1446 uint32_t delegate_data_size;
1447 char attr[GNUNET_ABD_MAX_LENGTH + 1];
1448 char issuer_attribute[GNUNET_ABD_MAX_LENGTH + 1];
1449 char *attrptr = attr;
1450 char *delegate_data;
1451 const char *utf_in;
1452
1453 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received VERIFY message\n");
1454 utf_in = (const char *) &v_msg[1];
1455 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
1456 GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
1457 issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
1458 vrh = GNUNET_new (struct VerifyRequestHandle);
1459 vrh->is_collect = false;
1460 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
1461 vrh->client = client;
1462 vrh->request_id = v_msg->id;
1463 vrh->issuer_key = v_msg->issuer_key;
1464 vrh->subject_key = v_msg->subject_key;
1465 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
1466 vrh->resolution_algo = ntohs (v_msg->resolution_algo);
1467
1468 vrh->del_chain_head = NULL;
1469 vrh->del_chain_tail = NULL;
1470 vrh->dsq_head = NULL;
1471 vrh->dsq_tail = NULL;
1472 vrh->del_chain_head = NULL;
1473 vrh->del_chain_tail = NULL;
1474
1475 GNUNET_SERVICE_client_continue (vrh->client);
1476 if (0 == strlen (issuer_attribute))
1477 {
1478 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer attribute provided!\n");
1479 send_lookup_response (vrh);
1480 return;
1481 }
1482
1483 // Parse delegates from verifaction message
1484 delegate_count = ntohl (v_msg->d_count);
1485 delegate_data_size = ntohs (v_msg->header.size)
1486 - sizeof (struct VerifyMessage)
1487 - ntohs (v_msg->issuer_attribute_len) - 1;
1488 struct GNUNET_ABD_Delegate delegates[delegate_count];
1489 memset (delegates,
1490 0,
1491 sizeof (struct GNUNET_ABD_Delegate) * delegate_count);
1492 delegate_data = (char *) &v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
1493 if (GNUNET_OK != GNUNET_ABD_delegates_deserialize (delegate_data_size,
1494 delegate_data,
1495 delegate_count,
1496 delegates))
1497 {
1498 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot deserialize delegates!\n");
1499 send_lookup_response (vrh);
1500 return;
1501 }
1502
1503 // Prepare vrh delegation chain for later validation
1504 for (uint32_t i = 0; i < delegate_count; i++)
1505 {
1506 del_entry = GNUNET_new (struct DelegateRecordEntry);
1507 del_entry->delegate =
1508 GNUNET_malloc (sizeof (struct GNUNET_ABD_Delegate)
1509 + delegates[i].issuer_attribute_len + 1);
1510 GNUNET_memcpy (del_entry->delegate,
1511 &delegates[i],
1512 sizeof (struct GNUNET_ABD_Delegate));
1513 GNUNET_memcpy (&del_entry->delegate[1],
1514 delegates[i].issuer_attribute,
1515 delegates[i].issuer_attribute_len);
1516 del_entry->delegate->issuer_attribute_len =
1517 delegates[i].issuer_attribute_len;
1518 del_entry->delegate->issuer_attribute = (char *) &del_entry->delegate[1];
1519 GNUNET_CONTAINER_DLL_insert_tail (vrh->del_chain_head,
1520 vrh->del_chain_tail,
1521 del_entry);
1522 vrh->del_chain_size++;
1523 }
1524
1525 // Switch resolution algo
1526 if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo &&
1527 GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
1528 {
1529 if (1 == delegation_chain_fw_resolution_start (vrh))
1530 return;
1531 delegation_chain_bw_resolution_start (vrh);
1532 }
1533 else if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo)
1534 {
1535 delegation_chain_bw_resolution_start (vrh);
1536 }
1537 else if (GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
1538 {
1539 delegation_chain_fw_resolution_start (vrh);
1540 }
1541}
1542
1543
1544static void
1545handle_delegate_collection_error_cb (void *cls)
1546{
1547 struct VerifyRequestHandle *vrh = cls;
1548 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1549 "Got disconnected from namestore database.\n");
1550 vrh->dele_qe = NULL;
1551 send_lookup_response (vrh);
1552}
1553
1554
1555static void
1556delegate_collection_finished (void *cls)
1557{
1558 struct VerifyRequestHandle *vrh = cls;
1559 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done collecting delegates.\n");
1560
1561 // if both are set: bidirectional search, meaning start both chain resolutions
1562 if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo &&
1563 GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
1564 {
1565 // if premature match found don't start bw resolution
1566 if (1 == delegation_chain_fw_resolution_start (vrh))
1567 return;
1568 delegation_chain_bw_resolution_start (vrh);
1569 }
1570 else if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo)
1571 {
1572 delegation_chain_bw_resolution_start (vrh);
1573 }
1574 else if (GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
1575 {
1576 delegation_chain_fw_resolution_start (vrh);
1577 }
1578}
1579
1580
1581static void
1582handle_delegate_collection_cb (void *cls,
1583 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
1584 const char *label,
1585 unsigned int rd_count,
1586 const struct GNUNET_GNSRECORD_Data *rd)
1587{
1588 struct VerifyRequestHandle *vrh = cls;
1589 struct GNUNET_ABD_Delegate *del;
1590 struct DelegateRecordEntry *del_entry;
1591 int cred_record_count;
1592 cred_record_count = 0;
1593 vrh->dele_qe = NULL;
1594
1595 for (uint32_t i = 0; i < rd_count; i++)
1596 {
1597 if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type)
1598 continue;
1599 cred_record_count++;
1600 del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
1601 if (NULL == del)
1602 {
1603 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid delegate found\n");
1604 continue;
1605 }
1606 // only add the entries that are explicitly marked as private
1607 // and therefore symbolize the end of a chain
1608 if (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)
1609 {
1610 del_entry = GNUNET_new (struct DelegateRecordEntry);
1611 del_entry->delegate = del;
1612 GNUNET_CONTAINER_DLL_insert_tail (vrh->del_chain_head,
1613 vrh->del_chain_tail,
1614 del_entry);
1615 vrh->del_chain_size++;
1616 }
1617 }
1618
1619 delegate_collection_finished (vrh);
1620}
1621
1622
1623static void
1624handle_collect (void *cls, const struct CollectMessage *c_msg)
1625{
1626 char attr[GNUNET_ABD_MAX_LENGTH + 1];
1627 char issuer_attribute[GNUNET_ABD_MAX_LENGTH + 1];
1628 struct VerifyRequestHandle *vrh;
1629 struct GNUNET_SERVICE_Client *client = cls;
1630 char *attrptr = attr;
1631 const char *utf_in;
1632
1633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received COLLECT message\n");
1634
1635 utf_in = (const char *) &c_msg[1];
1636 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
1637
1638 GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
1639 issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
1640 vrh = GNUNET_new (struct VerifyRequestHandle);
1641 vrh->is_collect = true;
1642 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
1643 vrh->client = client;
1644 vrh->request_id = c_msg->id;
1645 vrh->issuer_key = c_msg->issuer_key;
1646 GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key, &vrh->subject_key);
1647 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
1648 vrh->resolution_algo = ntohs (c_msg->resolution_algo);
1649
1650 vrh->del_chain_head = NULL;
1651 vrh->del_chain_tail = NULL;
1652 vrh->dsq_head = NULL;
1653 vrh->dsq_tail = NULL;
1654 vrh->del_chain_head = NULL;
1655 vrh->del_chain_tail = NULL;
1656
1657 if (0 == strlen (issuer_attribute))
1658 {
1659 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer attribute provided!\n");
1660 send_lookup_response (vrh);
1661 return;
1662 }
1663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting delegates for subject\n");
1664
1665 // Get all delegates from subject
1666 vrh->dele_qe =
1667 GNUNET_NAMESTORE_records_lookup (namestore,
1668 &c_msg->subject_key,
1669 GNUNET_GNS_EMPTY_LABEL_AT,
1670 &handle_delegate_collection_error_cb,
1671 vrh,
1672 &handle_delegate_collection_cb,
1673 vrh);
1674 GNUNET_SERVICE_client_continue (vrh->client);
1675}
1676
1677
1678static int
1679check_collect (void *cls, const struct CollectMessage *c_msg)
1680{
1681 size_t msg_size;
1682 const char *attr;
1683
1684 msg_size = ntohs (c_msg->header.size);
1685 if (msg_size < sizeof (struct CollectMessage))
1686 {
1687 GNUNET_break (0);
1688 return GNUNET_SYSERR;
1689 }
1690 if (ntohs (c_msg->issuer_attribute_len) > GNUNET_ABD_MAX_LENGTH)
1691 {
1692 GNUNET_break (0);
1693 return GNUNET_SYSERR;
1694 }
1695 attr = (const char *) &c_msg[1];
1696
1697 if (('\0' != attr[msg_size - sizeof (struct CollectMessage) - 1]) ||
1698 (strlen (attr) > GNUNET_ABD_MAX_LENGTH))
1699 {
1700 GNUNET_break (0);
1701 return GNUNET_SYSERR;
1702 }
1703 return GNUNET_OK;
1704}
1705
1706
1707static void
1708client_disconnect_cb (void *cls,
1709 struct GNUNET_SERVICE_Client *client,
1710 void *app_ctx)
1711{
1712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1713}
1714
1715
1716static void *
1717client_connect_cb (void *cls,
1718 struct GNUNET_SERVICE_Client *client,
1719 struct GNUNET_MQ_Handle *mq)
1720{
1721 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1722 return client;
1723}
1724
1725
1726/**
1727 * Process Credential requests.
1728 *
1729 * @param cls closure
1730 * @param c configuration to use
1731 * @param handle service handle
1732 */
1733static void
1734run (void *cls,
1735 const struct GNUNET_CONFIGURATION_Handle *c,
1736 struct GNUNET_SERVICE_Handle *handle)
1737{
1738
1739 gns = GNUNET_GNS_connect (c);
1740 if (NULL == gns)
1741 {
1742 fprintf (stderr, _ ("Failed to connect to GNS\n"));
1743 }
1744 namestore = GNUNET_NAMESTORE_connect (c);
1745 if (NULL == namestore)
1746 {
1747 fprintf (stderr, _ ("Failed to connect to namestore\n"));
1748 }
1749
1750 statistics = GNUNET_STATISTICS_create ("abd", c);
1751 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1752}
1753
1754
1755/**
1756 * Define "main" method using service macro
1757 */
1758GNUNET_SERVICE_MAIN (
1759 "abd",
1760 GNUNET_SERVICE_OPTION_NONE,
1761 &run,
1762 &client_connect_cb,
1763 &client_disconnect_cb,
1764 NULL,
1765 GNUNET_MQ_hd_var_size (verify,
1766 GNUNET_MESSAGE_TYPE_ABD_VERIFY,
1767 struct VerifyMessage,
1768 NULL),
1769 GNUNET_MQ_hd_var_size (collect,
1770 GNUNET_MESSAGE_TYPE_ABD_COLLECT,
1771 struct CollectMessage,
1772 NULL),
1773 GNUNET_MQ_handler_end ());
1774
1775/* end of gnunet-service-abd.c */