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