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