2 This file is part of GNUnet.
3 Copyright (C) 2011-2013 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @file abd/gnunet-service-abd.c
22 * @brief GNUnet Credential Service (main service)
23 * @author Martin Schanzenbach
27 #include "gnunet_util_lib.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>
42 #define GNUNET_ABD_MAX_LENGTH 255
44 struct VerifyRequestHandle;
46 struct DelegationSetQueueEntry;
49 struct DelegationChainEntry
54 struct DelegationChainEntry *next;
59 struct DelegationChainEntry *prev;
64 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
69 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
72 * The issued attribute
74 char *issuer_attribute;
77 * The delegated attribute
79 char *subject_attribute;
85 struct DelegateRecordEntry
90 struct DelegateRecordEntry *next;
95 struct DelegateRecordEntry *prev;
98 * Number of references in delegation chains
105 struct GNUNET_ABD_Delegate *delegate;
109 * DLL used for delegations
110 * Used for OR delegations
112 struct DelegationQueueEntry
117 struct DelegationQueueEntry *next;
122 struct DelegationQueueEntry *prev;
127 struct DelegationSetQueueEntry *parent_set;
132 uint32_t required_solutions;
136 * DLL for delegation sets
137 * Used for AND delegation set
139 struct DelegationSetQueueEntry
144 struct DelegationSetQueueEntry *next;
149 struct DelegationSetQueueEntry *prev;
154 struct GNUNET_GNS_LookupRequest *lookup_request;
159 struct VerifyRequestHandle *handle;
162 * Parent attribute delegation
164 struct DelegationQueueEntry *parent;
169 struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key;
172 * Queue entries of this set
174 struct DelegationQueueEntry *queue_entries_head;
177 * Queue entries of this set
179 struct DelegationQueueEntry *queue_entries_tail;
184 struct DelegationQueueEntry *parent_queue_entry;
187 * Issuer attribute delegated to
189 char *issuer_attribute;
192 * The current attribute to look up
194 char *lookup_attribute;
197 * Trailing attribute context
202 * Still to resolve delegation as string
204 char *unresolved_attribute_delegation;
207 * The delegation chain entry
209 struct DelegationChainEntry *delegation_chain_entry;
212 * True if added by backward resolution
219 * Handle to a lookup operation from api
221 struct VerifyRequestHandle
224 * True if created by a collect request.
228 * We keep these in a DLL.
230 struct VerifyRequestHandle *next;
233 * We keep these in a DLL.
235 struct VerifyRequestHandle *prev;
238 * Handle to the requesting client
240 struct GNUNET_SERVICE_Client *client;
243 * Size of delegation tree
245 uint32_t delegation_chain_size;
248 * Children of this attribute
250 struct DelegationChainEntry *delegation_chain_head;
253 * Children of this attribute
255 struct DelegationChainEntry *delegation_chain_tail;
258 * List for bidirectional matching
260 struct DelegationSetQueueEntry *dsq_head;
263 * List for bidirectional matching
265 struct DelegationSetQueueEntry *dsq_tail;
270 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
275 char *issuer_attribute;
280 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
285 struct DelegateRecordEntry *del_chain_head;
290 struct DelegateRecordEntry *del_chain_tail;
295 uint32_t del_chain_size;
298 * Current Delegation Pointer
300 struct DelegationQueueEntry *current_delegation;
310 uint64_t pending_lookups;
313 * Direction of the resolution algo
315 enum GNUNET_ABD_AlgoDirectionFlags resolution_algo;
318 * Delegate iterator for lookup
320 struct GNUNET_NAMESTORE_QueueEntry *dele_qe;
327 static struct VerifyRequestHandle *vrh_head = NULL;
332 static struct VerifyRequestHandle *vrh_tail = NULL;
335 * Handle to the statistics service
337 static struct GNUNET_STATISTICS_Handle *statistics;
340 * Handle to GNS service.
342 static struct GNUNET_GNS_Handle *gns;
345 * Handle to namestore service
347 static struct GNUNET_NAMESTORE_Handle *namestore;
350 print_deleset (struct DelegationSetQueueEntry *dsentry, char *text)
352 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
353 "%s %s.%s <- %s.%s\n",
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);
365 cleanup_dsq_entry (struct DelegationSetQueueEntry *ds_entry)
367 GNUNET_free_non_null (ds_entry->issuer_key);
368 GNUNET_free_non_null (ds_entry->issuer_attribute);
369 GNUNET_free_non_null (ds_entry->attr_trailer);
370 // those fields are only set/used in bw search
371 if (ds_entry->from_bw)
373 GNUNET_free_non_null (ds_entry->lookup_attribute);
374 GNUNET_free_non_null (ds_entry->unresolved_attribute_delegation);
376 if (NULL != ds_entry->lookup_request)
378 GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
379 ds_entry->lookup_request = NULL;
381 if (NULL != ds_entry->delegation_chain_entry)
383 GNUNET_free_non_null (
384 ds_entry->delegation_chain_entry->subject_attribute);
385 GNUNET_free_non_null (ds_entry->delegation_chain_entry->issuer_attribute);
386 GNUNET_free (ds_entry->delegation_chain_entry);
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)
393 GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
394 ds_entry->queue_entries_tail,
396 GNUNET_free (dq_entry);
398 GNUNET_free (ds_entry);
403 cleanup_handle (struct VerifyRequestHandle *vrh)
405 struct DelegateRecordEntry *del_entry;
406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up...\n");
408 if (NULL != vrh->dsq_head)
410 for (struct DelegationSetQueueEntry *ds_entry = vrh->dsq_head; NULL !=
412 ds_entry = vrh->dsq_head)
414 GNUNET_CONTAINER_DLL_remove (vrh->dsq_head, vrh->dsq_tail, ds_entry);
415 cleanup_dsq_entry (ds_entry);
418 if (NULL != vrh->del_chain_head)
420 for (del_entry = vrh->del_chain_head; NULL != vrh->del_chain_head;
421 del_entry = vrh->del_chain_head)
423 GNUNET_CONTAINER_DLL_remove (vrh->del_chain_head,
426 GNUNET_free_non_null (del_entry->delegate);
427 GNUNET_free (del_entry);
430 GNUNET_free_non_null (vrh->issuer_attribute);
436 shutdown_task (void *cls)
438 struct VerifyRequestHandle *vrh;
440 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down!\n");
442 while (NULL != (vrh = vrh_head))
444 // ABD_resolver_lookup_cancel (clh->lookup);
445 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
446 cleanup_handle (vrh);
451 GNUNET_GNS_disconnect (gns);
454 if (NULL != namestore)
456 GNUNET_NAMESTORE_disconnect (namestore);
459 if (NULL != statistics)
461 GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
468 send_intermediate_response (struct VerifyRequestHandle *vrh, struct
469 DelegationChainEntry *ch_entry, bool is_bw)
471 struct DelegationChainIntermediateMessage *rmsg;
472 struct GNUNET_MQ_Envelope *env;
473 struct GNUNET_ABD_Delegation *dd;
476 // Don't report immediate results during collect
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)
489 dd->subject_attribute = ch_entry->subject_attribute;
490 dd->subject_attribute_len = strlen (ch_entry->subject_attribute) + 1;
494 size = GNUNET_ABD_delegation_chain_get_size (1,
499 env = GNUNET_MQ_msg_extra (rmsg,
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);
508 -1 != GNUNET_ABD_delegation_chain_serialize (1,
514 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (vrh->client), env);
519 send_lookup_response (struct VerifyRequestHandle *vrh)
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;
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++)
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)
542 dd[i].subject_attribute = dce->subject_attribute;
543 dd[i].subject_attribute_len = strlen (dce->subject_attribute) + 1;
548 // Remove all not needed credentials
549 for (del = vrh->del_chain_head; NULL != del;)
551 if (del->refcount > 0)
558 GNUNET_CONTAINER_DLL_remove (vrh->del_chain_head, vrh->del_chain_tail, tmp);
559 GNUNET_free (tmp->delegate);
561 vrh->del_chain_size--;
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++)
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;
580 GNUNET_ABD_delegation_chain_get_size (vrh->delegation_chain_size,
584 env = GNUNET_MQ_msg_extra (rmsg,
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);
592 if (0 < vrh->del_chain_size)
593 rmsg->del_found = htonl (GNUNET_YES);
595 rmsg->del_found = htonl (GNUNET_NO);
599 GNUNET_ABD_delegation_chain_serialize (vrh->delegation_chain_size,
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",
617 partial_match (char *tmp_trail,
620 char *issuer_attribute)
622 char *saveptr1, *saveptr2;
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)
634 if (0 == strcmp (trail_token, sub_token))
636 // good, matches, remove
640 // not relevant for solving the chain, end for iteration here
644 trail_token = strtok_r (NULL, ".", &saveptr1);
645 sub_token = strtok_r (NULL, ".", &saveptr2);
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)
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
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)
665 GNUNET_asprintf (&attr_trailer, "%s.%s", parent_trail, trail_token);
666 trail_token = strtok_r (NULL, ".", &saveptr1);
668 GNUNET_asprintf (&attr_trailer, "%s.%s", issuer_attribute, attr_trailer);
674 handle_bidirectional_match (struct DelegationSetQueueEntry *actual_entry,
675 struct DelegationSetQueueEntry *match_entry,
676 struct VerifyRequestHandle *vrh)
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)
684 old_fw_parent = fw_entry->parent_queue_entry->parent_set;
686 fw_entry->parent_queue_entry->parent_set = last_entry;
688 last_entry = fw_entry;
689 fw_entry = old_fw_parent;
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;
696 del_entry = del_entry->next)
698 if (0 != memcmp (&last_entry->delegation_chain_entry->subject_key,
699 &del_entry->delegate->issuer_key,
700 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
702 if (0 != strcmp (last_entry->delegation_chain_entry->subject_attribute,
703 del_entry->delegate->issuer_attribute))
706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found delegate.\n");
707 // increase refcount of the start delegation
708 del_entry->refcount++;
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)
715 tmp_set->parent_queue_entry->required_solutions--;
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);
723 // if one node on the path still needs solutions, this current
724 // patch cannot fullfil 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)
729 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
730 "Chain requires more solutions, waiting...\n");
739 forward_resolution (void *cls,
741 const struct GNUNET_GNSRECORD_Data *rd)
743 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d entries.\n", rd_count);
745 struct VerifyRequestHandle *vrh;
746 struct DelegationSetQueueEntry *current_set;
747 struct DelegationSetQueueEntry *ds_entry;
748 struct DelegationQueueEntry *dq_entry;
751 // set handle to NULL (as el = NULL)
752 current_set->lookup_request = NULL;
753 vrh = current_set->handle;
754 vrh->pending_lookups--;
756 // Loop record entries
757 for (uint32_t i = 0; i < rd_count; i++)
759 if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type)
762 // Start deserialize into Delegate
763 struct GNUNET_ABD_Delegate *del;
764 del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
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;
772 // Insert it into the current set
773 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
774 current_set->queue_entries_tail,
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;
788 // 1. complete match: trailer = 0, validate
789 // 2. partial match: replace
790 // 3. new solution: replace, add trailer
792 // At resolution chain start trailer of parent is NULL
793 if (NULL == current_set->attr_trailer)
795 // for (5) F.c <- G, remember .c when going upwards
796 ds_entry->attr_trailer = GNUNET_strdup (del->issuer_attribute);
800 if (0 == del->subject_attribute_len)
802 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: New solution\n");
804 // create new trailer del->issuer_attribute, ds_entry->attr_trailer
805 GNUNET_asprintf (&ds_entry->attr_trailer,
807 del->issuer_attribute,
808 current_set->attr_trailer);
810 else if (0 == strcmp (del->subject_attribute, current_set->attr_trailer))
813 // new trailer == issuer attribute (e.g. (5) to (4))
814 ds_entry->attr_trailer = GNUNET_strdup (del->issuer_attribute);
818 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: Partial match\n");
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));
826 // if null: skip this record entry (reasons: mismatch or overmatch, both not relevant)
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 (
833 del->issuer_attribute,
834 GNUNET_CRYPTO_ecdsa_public_key_to_string (
836 del->subject_attribute);
840 ds_entry->attr_trailer = trail;
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,
850 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
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);
861 // Found new entry, repoting intermediate result
862 send_intermediate_response (vrh, ds_entry->delegation_chain_entry, false);
864 // current delegation as parent
865 ds_entry->parent_queue_entry = dq_entry;
867 // Check for solution
868 // if: issuer key we looking for
869 if (0 == memcmp (&del->issuer_key,
871 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
873 // if: issuer attr we looking for
874 if (0 == strcmp (del->issuer_attribute, vrh->issuer_attribute))
876 // if: complete match, meaning new trailer == issuer attr
877 if (0 == strcmp (vrh->issuer_attribute, ds_entry->attr_trailer))
879 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: Solution\n");
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)
886 if (NULL != tmp_set->delegation_chain_entry)
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);
895 // Increase refcount for this delegate
896 for (struct DelegateRecordEntry *del_entry = vrh->del_chain_head;
898 del_entry = del_entry->next)
900 if (0 == memcmp (&del_entry->delegate->issuer_key,
901 &vrh->delegation_chain_head->subject_key,
902 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
904 if (0 == strcmp (del_entry->delegate->issuer_attribute,
905 vrh->delegation_chain_head->subject_attribute))
907 del_entry->refcount++;
912 send_lookup_response (vrh);
918 // Check for bidirectional crossmatch
919 for (struct DelegationSetQueueEntry *del_entry = vrh->dsq_head;
921 del_entry = del_entry->next)
923 // only check entries not by backward algorithm
924 if (del_entry->from_bw)
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)))
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))
935 print_deleset (del_entry, "Forward:");
936 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
937 "Forward: Found match with above!\n");
939 // one node on the path still needs solutions: return
941 handle_bidirectional_match (ds_entry, del_entry, vrh))
944 send_lookup_response (vrh);
951 // Starting a new GNS lookup
952 vrh->pending_lookups++;
953 ds_entry->handle = vrh;
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));
960 ds_entry->lookup_request =
961 GNUNET_GNS_lookup (gns,
962 GNUNET_GNS_EMPTY_LABEL_AT,
964 GNUNET_GNSRECORD_TYPE_DELEGATE,
965 GNUNET_GNS_LO_DEFAULT,
970 if (0 == vrh->pending_lookups)
972 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We are all out of attributes...\n");
973 send_lookup_response (vrh);
980 backward_resolution (void *cls,
982 const struct GNUNET_GNSRECORD_Data *rd)
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;
992 char *lookup_attribute;
995 current_set->lookup_request = NULL;
996 vrh = current_set->handle;
997 vrh->pending_lookups--;
1000 for (uint32_t i = 0; i < rd_count; i++)
1002 if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
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));
1012 GNUNET_ABD_delegation_set_deserialize (GNUNET_ntohll (
1014 (const char *) &sets[1],
1015 ntohl (sets->set_count),
1018 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to deserialize!\n");
1021 dq_entry = GNUNET_new (struct DelegationQueueEntry);
1022 dq_entry->required_solutions = ntohl (sets->set_count);
1023 dq_entry->parent_set = current_set;
1025 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
1026 current_set->queue_entries_tail,
1029 for (uint32_t j = 0; j < ntohl (sets->set_count); j++)
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;
1035 if (NULL != current_set->attr_trailer)
1037 if (0 == set[j].subject_attribute_len)
1039 GNUNET_asprintf (&expanded_attr, "%s", current_set->attr_trailer);
1043 GNUNET_asprintf (&expanded_attr,
1045 set[j].subject_attribute,
1046 current_set->attr_trailer);
1048 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expanded to %s\n", expanded_attr);
1049 ds_entry->unresolved_attribute_delegation = expanded_attr;
1053 if (0 != set[j].subject_attribute_len)
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);
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);
1078 // Found new entry, repoting intermediate result
1079 send_intermediate_response (vrh, ds_entry->delegation_chain_entry, true);
1081 ds_entry->parent_queue_entry = dq_entry; // current_delegation;
1084 * Check if this delegation already matches one of our credentials
1086 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking for cred match\n");
1088 for (del_pointer = vrh->del_chain_head; del_pointer != NULL;
1089 del_pointer = del_pointer->next)
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)))
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);
1101 if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
1102 del_pointer->delegate->issuer_attribute))
1105 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found issuer\n");
1106 // increase refcount of the start delegation
1107 del_pointer->refcount++;
1110 for (tmp_set = ds_entry; NULL != tmp_set->parent_queue_entry;
1111 tmp_set = tmp_set->parent_queue_entry->parent_set)
1113 tmp_set->parent_queue_entry->required_solutions--;
1114 if (NULL != tmp_set->delegation_chain_entry)
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);
1121 if (0 < tmp_set->parent_queue_entry->required_solutions)
1125 // if the break above is not called the condition of the for is met
1126 if (NULL == tmp_set->parent_queue_entry)
1128 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All solutions found\n");
1130 send_lookup_response (vrh);
1133 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not all solutions found yet.\n");
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)
1144 strcpy (issuer_attribute_name, ds_entry->unresolved_attribute_delegation);
1145 char *next_attr = strtok (issuer_attribute_name, ".");
1146 if (NULL == next_attr)
1148 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1149 "Failed to parse next attribute\n");
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))
1157 ds_entry->attr_trailer = NULL;
1161 next_attr += strlen (next_attr) + 1;
1162 ds_entry->attr_trailer = GNUNET_strdup (next_attr);
1165 // Check for bidirectional crossmatch
1166 for (struct DelegationSetQueueEntry *del_entry = vrh->dsq_head;
1168 del_entry = del_entry->next)
1170 // only check entries added by forward algorithm
1171 if (! del_entry->from_bw)
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)))
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))
1182 print_deleset (del_entry, "Backward:");
1183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1184 "Backward: Found match with above!\n");
1186 // if one node on the path still needs solutions: return
1188 handle_bidirectional_match (del_entry, ds_entry, vrh))
1191 // Send lookup response
1192 send_lookup_response (vrh);
1199 // Starting a new GNS lookup
1200 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
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);
1208 vrh->pending_lookups++;
1209 ds_entry->handle = vrh;
1210 ds_entry->lookup_request =
1211 GNUNET_GNS_lookup (gns,
1213 ds_entry->issuer_key, // issuer_key,
1214 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
1215 GNUNET_GNS_LO_DEFAULT,
1216 &backward_resolution,
1219 GNUNET_free (lookup_attribute);
1223 if (0 == vrh->pending_lookups)
1225 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We are all out of attributes...\n");
1226 send_lookup_response (vrh);
1233 * Result from GNS lookup.
1235 * @param cls the closure (our client lookup handle)
1238 delegation_chain_bw_resolution_start (void *cls)
1240 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Start Backward Resolution...\n");
1242 struct VerifyRequestHandle *vrh = cls;
1243 struct DelegationSetQueueEntry *ds_entry;
1244 struct DelegateRecordEntry *del_entry;
1246 if (0 == vrh->del_chain_size)
1248 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No delegates found\n");
1249 send_lookup_response (vrh);
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
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)
1263 if (0 != memcmp (&del_entry->delegate->issuer_key,
1265 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
1268 strcmp (del_entry->delegate->issuer_attribute, vrh->issuer_attribute))
1270 del_entry->refcount++;
1271 // Found match prematurely
1272 send_lookup_response (vrh);
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,
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,
1290 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1291 ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
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);
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;
1303 // Start with backward resolution
1304 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start Backward Resolution\n");
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,
1318 delegation_chain_fw_resolution_start (void *cls)
1320 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Start Forward Resolution...\n");
1322 struct VerifyRequestHandle *vrh = cls;
1323 struct DelegationSetQueueEntry *ds_entry;
1324 struct DelegateRecordEntry *del_entry;
1326 // set to 0 and increase on each lookup: for fw multiple lookups (may be) started
1327 vrh->pending_lookups = 0;
1329 if (0 == vrh->del_chain_size)
1331 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No delegations found\n");
1332 send_lookup_response (vrh);
1336 // Pre-check with vrh->dele_chain_.. if match issuer_key
1337 // otherwise FW: start mutliple lookups for each vrh->dele_chain
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)
1345 if (0 != memcmp (&del_entry->delegate->issuer_key,
1347 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
1350 strcmp (del_entry->delegate->issuer_attribute, vrh->issuer_attribute))
1352 del_entry->refcount++;
1353 // Found match prematurely
1354 send_lookup_response (vrh);
1358 // None match, therefore start for every delegation found a lookup chain
1359 // Return and end collect process on first chain iss <-> sub found
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)
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);
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));
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);
1390 ds_entry->attr_trailer =
1391 GNUNET_strdup (del_entry->delegate->issuer_attribute);
1392 ds_entry->handle = vrh;
1394 vrh->pending_lookups++;
1395 // Start with forward resolution
1396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start Forward Resolution\n");
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,
1412 check_verify (void *cls, const struct VerifyMessage *v_msg)
1417 msg_size = ntohs (v_msg->header.size);
1418 if (msg_size < sizeof (struct VerifyMessage))
1421 return GNUNET_SYSERR;
1423 if (ntohs (v_msg->issuer_attribute_len) > GNUNET_ABD_MAX_LENGTH)
1426 return GNUNET_SYSERR;
1428 attr = (const char *) &v_msg[1];
1430 if (strlen (attr) > GNUNET_ABD_MAX_LENGTH)
1433 return GNUNET_SYSERR;
1440 handle_verify (void *cls, const struct VerifyMessage *v_msg)
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;
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);
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;
1475 GNUNET_SERVICE_client_continue (vrh->client);
1476 if (0 == strlen (issuer_attribute))
1478 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer attribute provided!\n");
1479 send_lookup_response (vrh);
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];
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,
1498 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot deserialize delegates!\n");
1499 send_lookup_response (vrh);
1503 // Prepare vrh delegation chain for later validation
1504 for (uint32_t i = 0; i < delegate_count; i++)
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,
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,
1522 vrh->del_chain_size++;
1525 // Switch resolution algo
1526 if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo &&
1527 GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
1529 if (1 == delegation_chain_fw_resolution_start (vrh))
1531 delegation_chain_bw_resolution_start (vrh);
1533 else if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo)
1535 delegation_chain_bw_resolution_start (vrh);
1537 else if (GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
1539 delegation_chain_fw_resolution_start (vrh);
1545 handle_delegate_collection_error_cb (void *cls)
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);
1556 delegate_collection_finished (void *cls)
1558 struct VerifyRequestHandle *vrh = cls;
1559 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done collecting delegates.\n");
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)
1565 // if premature match found don't start bw resultion
1566 if (1 == delegation_chain_fw_resolution_start (vrh))
1568 delegation_chain_bw_resolution_start (vrh);
1570 else if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo)
1572 delegation_chain_bw_resolution_start (vrh);
1574 else if (GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
1576 delegation_chain_fw_resolution_start (vrh);
1582 handle_delegate_collection_cb (void *cls,
1583 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
1585 unsigned int rd_count,
1586 const struct GNUNET_GNSRECORD_Data *rd)
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;
1595 for (uint32_t i = 0; i < rd_count; i++)
1597 if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type)
1599 cred_record_count++;
1600 del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
1603 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid delegate found\n");
1606 // only add the entries that are explicity marked as private
1607 // and therefor symbolize the end of a chain
1608 if (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)
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,
1615 vrh->del_chain_size++;
1619 delegate_collection_finished (vrh);
1624 handle_collect (void *cls, const struct CollectMessage *c_msg)
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;
1633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received COLLECT message\n");
1635 utf_in = (const char *) &c_msg[1];
1636 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
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);
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;
1657 if (0 == strlen (issuer_attribute))
1659 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer attribute provided!\n");
1660 send_lookup_response (vrh);
1663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting delegates for subject\n");
1665 // Get all delegates from subject
1667 GNUNET_NAMESTORE_records_lookup (namestore,
1668 &c_msg->subject_key,
1669 GNUNET_GNS_EMPTY_LABEL_AT,
1670 &handle_delegate_collection_error_cb,
1672 &handle_delegate_collection_cb,
1674 GNUNET_SERVICE_client_continue (vrh->client);
1679 check_collect (void *cls, const struct CollectMessage *c_msg)
1684 msg_size = ntohs (c_msg->header.size);
1685 if (msg_size < sizeof (struct CollectMessage))
1688 return GNUNET_SYSERR;
1690 if (ntohs (c_msg->issuer_attribute_len) > GNUNET_ABD_MAX_LENGTH)
1693 return GNUNET_SYSERR;
1695 attr = (const char *) &c_msg[1];
1697 if (('\0' != attr[msg_size - sizeof (struct CollectMessage) - 1]) ||
1698 (strlen (attr) > GNUNET_ABD_MAX_LENGTH))
1701 return GNUNET_SYSERR;
1708 client_disconnect_cb (void *cls,
1709 struct GNUNET_SERVICE_Client *client,
1712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1717 client_connect_cb (void *cls,
1718 struct GNUNET_SERVICE_Client *client,
1719 struct GNUNET_MQ_Handle *mq)
1721 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1727 * Process Credential requests.
1729 * @param cls closure
1730 * @param c configuration to use
1731 * @param handle service handle
1735 const struct GNUNET_CONFIGURATION_Handle *c,
1736 struct GNUNET_SERVICE_Handle *handle)
1739 gns = GNUNET_GNS_connect (c);
1742 fprintf (stderr, _ ("Failed to connect to GNS\n"));
1744 namestore = GNUNET_NAMESTORE_connect (c);
1745 if (NULL == namestore)
1747 fprintf (stderr, _ ("Failed to connect to namestore\n"));
1750 statistics = GNUNET_STATISTICS_create ("abd", c);
1751 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1756 * Define "main" method using service macro
1758 GNUNET_SERVICE_MAIN (
1760 GNUNET_SERVICE_OPTION_NONE,
1763 &client_disconnect_cb,
1765 GNUNET_MQ_hd_var_size (verify,
1766 GNUNET_MESSAGE_TYPE_ABD_VERIFY,
1767 struct VerifyMessage,
1769 GNUNET_MQ_hd_var_size (collect,
1770 GNUNET_MESSAGE_TYPE_ABD_COLLECT,
1771 struct CollectMessage,
1773 GNUNET_MQ_handler_end ());
1775 /* end of gnunet-service-abd.c */