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