GNUnet  0.11.x
gnunet-service-abd.c
Go to the documentation of this file.
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 */
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"
35 #include <gnunet_dnsparser_lib.h>
36 #include <gnunet_gns_service.h>
37 #include <gnunet_gnsrecord_lib.h>
40 
41 
42 #define GNUNET_ABD_MAX_LENGTH 255
43 
44 struct VerifyRequestHandle;
45 
47 
48 
50 {
55 
60 
65 
70 
75 
80 };
81 
86 {
91 
96 
100  uint32_t refcount;
101 
106 };
107 
113 {
118 
123 
128 
133 };
134 
140 {
145 
150 
155 
160 
165 
170 
175 
180 
185 
190 
195 
200 
205 
210 
214  bool from_bw;
215 };
216 
217 
222 {
231 
236 
241 
246 
251 
256 
261 
266 
271 
276 
281 
286 
291 
295  uint32_t del_chain_size;
296 
301 
305  uint32_t request_id;
306 
310  uint64_t pending_lookups;
311 
315  enum GNUNET_ABD_AlgoDirectionFlags resolution_algo;
316 
321 };
322 
323 
327 static struct VerifyRequestHandle *vrh_head = NULL;
328 
332 static struct VerifyRequestHandle *vrh_tail = NULL;
333 
338 
342 static struct GNUNET_GNS_Handle *gns;
343 
348 
349 static void
350 print_deleset (struct DelegationSetQueueEntry *dsentry, char *text)
351 {
353  "%s %s.%s <- %s.%s\n",
354  text,
361 }
362 
363 static void
365 {
366  GNUNET_free_non_null (ds_entry->issuer_key);
369  // those fields are only set/used in bw search
370  if (ds_entry->from_bw)
371  {
374  }
375  if (NULL != ds_entry->lookup_request)
376  {
378  ds_entry->lookup_request = NULL;
379  }
380  if (NULL != ds_entry->delegation_chain_entry)
381  {
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  {
393  ds_entry->queue_entries_tail,
394  dq_entry);
395  GNUNET_free (dq_entry);
396  }
397  GNUNET_free (ds_entry);
398 }
399 
400 static void
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  {
421  vrh->del_chain_tail,
422  del_entry);
423  GNUNET_free_non_null (del_entry->delegate);
424  GNUNET_free (del_entry);
425  }
426  }
428  GNUNET_free (vrh);
429 }
430 
431 static void
432 shutdown_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 
462 static void
463 send_intermediate_response(struct VerifyRequestHandle *vrh, struct DelegationChainEntry *ch_entry, bool is_bw){
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 
488  dd,
489  0,
490  NULL);
491 
492  env = GNUNET_MQ_msg_extra (rmsg,
493  size,
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 (
502  dd,
503  0,
504  NULL,
505  size,
506  (char *) &rmsg[1]));
508 }
509 
510 static void
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  {
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;
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,
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 
607 static char *
608 partial_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 
663 static int
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++;
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  {
720  "Chain requires more solutions, waiting...\n");
721  return GNUNET_NO;
722  }
723  }
724  return GNUNET_YES;
725 }
726 
727 static void
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
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),
812  current_set->attr_trailer,
814 
815  // if null: skip this record entry (reasons: mismatch or overmatch, both not relevant)
816  if (NULL == trail)
817  {
819  "Entry not relevant, discarding: %s.%s <- %s.%s\n",
821  &del->issuer_key),
822  del->issuer_attribute,
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)
837  GNUNET_memcpy (ds_entry->issuer_key,
838  &del->subject_key,
839  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
840 
843  if (0 < del->subject_attribute_len)
846  ds_entry->delegation_chain_entry->issuer_key = del->issuer_key;
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++;
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,
891  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
892  {
893  if (0 == strcmp (del_entry->delegate->issuer_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,
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:");
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 
945  "Starting to look up trailer %s in zone %s\n",
946  ds_entry->attr_trailer,
948 
949  ds_entry->lookup_request =
950  GNUNET_GNS_lookup (gns,
952  &del->issuer_key,
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 
967 static void
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)];
996  "Found new attribute delegation with %d sets. Creating new Job...\n",
997  ntohl (sets->set_count));
998 
999  if (GNUNET_OK !=
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 
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  {
1044  "Not Expanding %s\n",
1045  set[j].subject_attribute);
1047  GNUNET_strdup (set[j].subject_attribute);
1048  }
1049  }
1050 
1051  // Add a credential chain entry
1052  ds_entry->delegation_chain_entry =
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)
1062  ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
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 
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;
1085  "Checking if %s matches %s\n",
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  {
1102  if (NULL != tmp_set->delegation_chain_entry)
1103  {
1104  vrh->delegation_chain_size++;
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 
1126  "Building new lookup request from %s\n",
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  {
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,
1169  {
1170  print_deleset (del_entry, "Backward:");
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
1189  "Looking up %s\n",
1190  ds_entry->lookup_attribute);
1191  if (NULL != ds_entry->attr_trailer)
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,
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 
1225 static int
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);
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 
1282  ds_entry->delegation_chain_entry->issuer_key = vrh->issuer_key;
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,
1300  ds_entry);
1301  return 0;
1302 }
1303 
1304 static int
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 
1355  "Looking for %s.%s\n",
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 
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;
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,
1386  &del_entry->delegate->issuer_key, // issuer_key,
1390  ds_entry);
1391  }
1392  return 0;
1393 }
1394 
1395 static int
1396 check_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 
1422 static void
1423 handle_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];
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 
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];
1503  vrh->del_chain_tail,
1504  del_entry);
1505  vrh->del_chain_size++;
1506  }
1507 
1508  // Switch resolution algo
1511  {
1513  return;
1515  }
1516  else if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo)
1517  {
1519  }
1520  else if (GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
1521  {
1523  }
1524 }
1525 
1526 static void
1528 {
1529  struct VerifyRequestHandle *vrh = cls;
1531  "Got disconnected from namestore database.\n");
1532  vrh->dele_qe = NULL;
1533  send_lookup_response (vrh);
1534 }
1535 
1536 static void
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
1545  {
1546  // if premature match found don't start bw resultion
1548  return;
1550  }
1551  else if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo)
1552  {
1554  }
1555  else if (GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
1556  {
1558  }
1559 }
1560 
1561 static void
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;
1593  vrh->del_chain_tail,
1594  del_entry);
1595  vrh->del_chain_size++;
1596  }
1597  }
1598 
1600 }
1601 
1602 static void
1603 handle_collect (void *cls, const struct CollectMessage *c_msg)
1604 {
1605  char attr[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;
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 =
1647  &c_msg->subject_key,
1650  vrh,
1652  vrh);
1654 }
1655 
1656 
1657 static int
1658 check_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 
1685 static void
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 
1693 static void *
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 
1709 static void
1710 run (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);
1728 }
1729 
1730 
1735  "abd",
1737  &run,
1740  NULL,
1743  struct VerifyMessage,
1744  NULL),
1747  struct CollectMessage,
1748  NULL),
1750 
1751 /* end of gnunet-service-abd.c */
uint64_t pending_lookups
Pending lookups.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
struct VerifyRequestHandle * next
We keep these in a DLL.
Connection to the GNS service.
Definition: gns_api.h:35
Message from client to Credential service to verify attributes.
Definition: abd.h:74
#define GNUNET_MESSAGE_TYPE_ABD_INTERMEDIATE_RESULT
static void cleanup_handle(struct VerifyRequestHandle *vrh)
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
uint32_t id
Unique identifier for this request (for key collisions).
Definition: abd.h:128
struct GNUNET_CRYPTO_EcdsaPublicKey subject_key
Public key of the subject this credential was issued to.
struct DelegationQueueEntry * parent
Parent attribute delegation.
struct DelegationChainEntry * prev
DLL.
struct DelegationChainEntry * delegation_chain_tail
Children of this attribute.
static void handle_verify(void *cls, const struct VerifyMessage *v_msg)
IPC messages between ABD API and ABD service.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
uint32_t issuer_attribute_len
Length of the attribute.
Handle to a service.
Definition: service.c:116
struct GNUNET_CRYPTO_EcdsaPublicKey subject_key
The subject.
struct VerifyRequestHandle * prev
We keep these in a DLL.
uint16_t issuer_attribute_len
Length of the issuer attribute.
Definition: abd.h:99
int GNUNET_ABD_delegates_deserialize(size_t len, const char *src, unsigned int c_count, struct GNUNET_ABD_Delegate *cd)
Deserialize the given destination.
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2437
struct DelegationSetQueueEntry * dsq_tail
List for bidirectional matching.
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_lookup(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, const char *label, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_NAMESTORE_RecordMonitor rm, void *rm_cls)
Lookup an item in the namestore.
uint16_t resolution_algo
Direction of the resolution algo.
Definition: abd.h:104
uint32_t id
Unique identifier for this request (for key collisions).
Definition: abd.h:109
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1300
Message from ABD service to client: new results.
Definition: abd.h:118
struct DelegateRecordEntry * prev
DLL.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
char * issuer_attribute
Issuer attribute.
uint32_t id
Unique identifier for this request (for key collisions).
Definition: abd.h:161
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
struct GNUNET_ABD_Delegate * delegate
Payload.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct DelegationChainEntry * delegation_chain_entry
The delegation chain entry.
Handle to a lookup request.
Definition: gns_api.c:42
struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key
Trust anchor.
Definition: abd.h:50
static struct VerifyRequestHandle * vrh_head
Head of the DLL.
GNUNET_ABD_AlgoDirectionFlags
static void send_lookup_response(struct VerifyRequestHandle *vrh)
The attribute delegation record.
char * issuer_attribute
Issuer attribute delegated to.
Message from client to Credential service to collect credentials.
Definition: abd.h:35
static void handle_delegate_collection_cb(void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
char * issuer_attribute
The issued attribute.
DLL for delegation sets Used for AND delegation set.
#define GNUNET_NO
Definition: gnunet_common.h:78
struct GNUNET_CRYPTO_EcdsaPublicKey subject_key
Subject public key.
Definition: abd.h:84
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
bool is_collect
True if created by a collect request.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Private ECC key encoded for transmission.
static int check_verify(void *cls, const struct VerifyMessage *v_msg)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct DelegationSetQueueEntry * next
DLL.
Message from ABD service to client: new results.
Definition: abd.h:151
Handle for the service.
struct DelegateRecordEntry * del_chain_tail
Delegate DLL.
struct GNUNET_CRYPTO_EcdsaSignature signature
Signature of this credential.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
bool from_bw
True if added by backward resolution.
struct GNUNET_GNS_LookupRequest * lookup_request
GNS handle.
struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key
The issuer of the credential.
static char * partial_match(char *tmp_trail, char *tmp_subattr, char *parent_trail, char *issuer_attribute)
ssize_t GNUNET_ABD_delegation_chain_serialize(unsigned int d_count, const struct GNUNET_ABD_Delegation *dd, unsigned int c_count, const struct GNUNET_ABD_Delegate *cd, size_t dest_size, char *dest)
Serizalize the given delegation chain entries and abd.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
enum GNUNET_ABD_AlgoDirectionFlags resolution_algo
Direction of the resolution algo.
struct DelegationQueueEntry * queue_entries_head
Queue entries of this set.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *handle)
Process Credential requests.
Handle to a client that is connected to a service.
Definition: service.c:250
struct DelegationChainEntry * next
DLL.
uint32_t request_id
request id
struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key
Issuer public key.
struct DelegationQueueEntry * current_delegation
Current Delegation Pointer.
void GNUNET_NAMESTORE_disconnect(struct GNUNET_NAMESTORE_Handle *h)
Disconnect from the namestore service (and free associated resources).
static int delegation_chain_fw_resolution_start(void *cls)
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#define GNUNET_GNSRECORD_TYPE_DELEGATE
65546 reserved
static int delegation_chain_bw_resolution_start(void *cls)
Result from GNS lookup.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
struct GNUNET_ABD_Delegate * GNUNET_ABD_delegate_deserialize(const char *data, size_t data_size)
uint32_t del_chain_size
Delegate DLL size.
const void * data
Binary value stored in the DNS record.
static int del
Desired action is to remove a record.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
static void backward_resolution(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Connection to the NAMESTORE service.
struct DelegationSetQueueEntry * prev
DLL.
void GNUNET_GNS_disconnect(struct GNUNET_GNS_Handle *handle)
Shutdown connection with the GNS service.
Definition: gns_api.c:284
DLL for record.
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_ABD_VERIFY.
Definition: abd.h:79
uint32_t subject_attribute_len
Length of the subject attribute.
uint16_t resolution_algo
Direction of the resolution algo.
Definition: abd.h:60
static void handle_delegate_collection_error_cb(void *cls)
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
struct VerifyRequestHandle * handle
Verify handle.
struct GNUNET_GNS_Handle * GNUNET_GNS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize the connection with the GNS service.
Definition: gns_api.c:262
This is a private record of this peer and it should thus not be handed out to other peers...
struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key
The issuer of the delegation.
char * GNUNET_CRYPTO_ecdsa_public_key_to_string(const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Convert a public key to a string.
Definition: crypto_ecc.c:332
struct DelegationChainEntry * delegation_chain_head
Children of this attribute.
static void forward_resolution(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
static int collect
Collect mode.
Definition: gnunet-abd.c:132
#define GNUNET_MESSAGE_TYPE_ABD_VERIFY
uint32_t issuer_attribute_len
Length of the issuer attribute.
size_t GNUNET_ABD_delegation_chain_get_size(unsigned int d_count, const struct GNUNET_ABD_Delegation *dd, unsigned int c_count, const struct GNUNET_ABD_Delegate *cd)
Calculate how many bytes we will need to serialize the given delegation chain and abd...
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
uint32_t refcount
Number of references in delegation chains.
static unsigned int size
Size of the "table".
Definition: peer.c:67
void GNUNET_CRYPTO_ecdsa_key_get_public(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:239
An QueueEntry used to store information for a pending NAMESTORE record operation. ...
Definition: namestore_api.c:53
struct DelegateRecordEntry * del_chain_head
Delegate DLL.
static void handle_collect(void *cls, const struct CollectMessage *c_msg)
Handle to a lookup operation from api.
uint32_t delegation_chain_size
Size of delegation tree.
struct GNUNET_NAMESTORE_Handle * GNUNET_NAMESTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the namestore service.
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
uint32_t id
Unique identifier for this request (for key collisions).
Definition: abd.h:65
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_ABD_VERIFY.
Definition: abd.h:40
struct DelegationQueueEntry * queue_entries_tail
Queue entries of this set.
#define GNUNET_MESSAGE_TYPE_ABD_VERIFY_RESULT
const char * subject_attribute
The attribute.
char * attr_trailer
Trailing attribute context.
const char * subject_attribute
The subject attribute.
static void delegate_collection_finished(void *cls)
int GNUNET_ABD_delegation_set_deserialize(size_t len, const char *src, unsigned int d_count, struct GNUNET_ABD_DelegationSet *dsr)
Deserialize the given destination.
uint32_t d_count
Number of delegates.
Definition: abd.h:94
struct GNUNET_CRYPTO_EcdsaPrivateKey subject_key
Subject public key.
Definition: abd.h:45
Handle to a message queue.
Definition: mq.c:85
GNUNET_SERVICE_MAIN("abd", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(verify, GNUNET_MESSAGE_TYPE_ABD_VERIFY, struct VerifyMessage, NULL), GNUNET_MQ_hd_var_size(collect, GNUNET_MESSAGE_TYPE_ABD_COLLECT, struct CollectMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
struct GNUNET_CRYPTO_EcdsaPublicKey subject_key
Public key of the subject this attribute was delegated to.
The attribute delegation record.
configuration data
Definition: configuration.c:85
#define GNUNET_MESSAGE_TYPE_ABD_COLLECT
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
static int check_collect(void *cls, const struct CollectMessage *c_msg)
struct DelegationQueueEntry * next
DLL.
#define GNUNET_GNSRECORD_TYPE_ATTRIBUTE
Record type for reverse lookups.
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
#define GNUNET_log(kind,...)
struct GNUNET_CRYPTO_EcdsaPublicKey subject_key
Subject public key.
void * GNUNET_GNS_lookup_cancel(struct GNUNET_GNS_LookupRequest *lr)
Cancel pending lookup request.
Definition: gns_api.c:308
struct GNUNET_NAMESTORE_QueueEntry * dele_qe
Delegate iterator for lookup.
struct GNUNET_TIME_Absolute expiration
Expiration of this credential.
static struct GNUNET_STATISTICS_Handle * statistics
Handle to the statistics service.
struct GNUNET_CRYPTO_EcdsaPublicKey * issuer_key
Issuer key.
struct DelegationSetQueueEntry * dsq_head
List for bidirectional matching.
struct GNUNET_SERVICE_Client * client
Handle to the requesting client.
uint16_t issuer_attribute_len
Length of the issuer attribute.
Definition: abd.h:55
uint32_t del_found
Indicates if credential has been found at all.
Definition: abd.h:133
#define GNUNET_YES
Definition: gnunet_common.h:77
char * subject_attribute
The delegated attribute.
Defaults, look in cache, then in DHT.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
#define GNUNET_ABD_MAX_LENGTH
uint32_t required_solutions
Required solutions.
static struct VerifyRequestHandle * vrh_tail
Tail of the DLL.
static struct GNUNET_GNS_Handle * gns
Handle to GNS service.
const char * issuer_attribute
The attribute.
const char * issuer_attribute
The issuer attribute.
static void shutdown_task(void *cls)
struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key
Trust anchor.
Definition: abd.h:89
static void send_intermediate_response(struct VerifyRequestHandle *vrh, struct DelegationChainEntry *ch_entry, bool is_bw)
struct GNUNET_GNS_LookupRequest * GNUNET_GNS_lookup(struct GNUNET_GNS_Handle *handle, const char *name, const struct GNUNET_CRYPTO_EcdsaPublicKey *zone, uint32_t type, enum GNUNET_GNS_LocalOptions options, GNUNET_GNS_LookupResultProcessor proc, void *proc_cls)
Perform an asynchronous lookup operation on the GNS.
Definition: gns_api.c:336
static void cleanup_dsq_entry(struct DelegationSetQueueEntry *ds_entry)
static int verify
Verify mode.
Definition: gnunet-abd.c:127
uint32_t data
The data value.
struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key
The issuer.
static void print_deleset(struct DelegationSetQueueEntry *dsentry, char *text)
API to serialize and deserialize delegation chains and abds.
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2243
struct DelegationQueueEntry * parent_queue_entry
Parent QueueEntry.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
uint32_t subject_attribute_len
Length of the attribute.
uint32_t d_count
The number of delegations in the response.
Definition: abd.h:138
#define GNUNET_malloc(size)
Wrapper around malloc.
static struct GNUNET_NAMESTORE_Handle * namestore
Handle to namestore service.
static int handle_bidirectional_match(struct DelegationSetQueueEntry *actual_entry, struct DelegationSetQueueEntry *match_entry, struct VerifyRequestHandle *vrh)
char * unresolved_attribute_delegation
Still to resolve delegation as string.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
uint32_t c_count
The number of credentials in the response.
Definition: abd.h:143
#define GNUNET_free(ptr)
Wrapper around free.
struct DelegationQueueEntry * prev
DLL.
DLL used for delegations Used for OR delegations.
struct DelegationSetQueueEntry * parent_set
Parent set.
void GNUNET_STRINGS_utf8_tolower(const char *input, char *output)
Convert the utf-8 input string to lower case.
Definition: strings.c:553
struct DelegateRecordEntry * next
DLL.
char * lookup_attribute
The current attribute to look up.