aboutsummaryrefslogtreecommitdiff
path: root/src/credential/gnunet-service-credential.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/credential/gnunet-service-credential.c')
-rw-r--r--src/credential/gnunet-service-credential.c1160
1 files changed, 1160 insertions, 0 deletions
diff --git a/src/credential/gnunet-service-credential.c b/src/credential/gnunet-service-credential.c
new file mode 100644
index 000000000..be88839e9
--- /dev/null
+++ b/src/credential/gnunet-service-credential.c
@@ -0,0 +1,1160 @@
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
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
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#include "gnunet_util_lib.h"
27#include "gnunet_credential_service.h"
28#include "gnunet_statistics_service.h"
29#include "credential.h"
30#include "credential_serialization.h"
31#include "gnunet_protocols.h"
32#include "gnunet_signatures.h"
33
34#include <gnunet_dnsparser_lib.h>
35#include <gnunet_identity_service.h>
36#include <gnunet_gnsrecord_lib.h>
37#include <gnunet_namestore_service.h>
38#include <gnunet_gns_service.h>
39
40
41#define GNUNET_CREDENTIAL_MAX_LENGTH 255
42
43struct VerifyRequestHandle;
44
45struct DelegationSetQueueEntry;
46
47
48struct DelegationChainEntry
49{
50 /**
51 * DLL
52 */
53 struct DelegationChainEntry *next;
54
55 /**
56 * DLL
57 */
58 struct DelegationChainEntry *prev;
59
60 /**
61 * The issuer
62 */
63 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
64
65 /**
66 * The subject
67 */
68 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
69
70 /**
71 * The issued attribute
72 */
73 char *issuer_attribute;
74
75 /**
76 * The delegated attribute
77 */
78 char *subject_attribute;
79};
80
81/**
82 * DLL for record
83 */
84struct CredentialRecordEntry
85{
86 /**
87 * DLL
88 */
89 struct CredentialRecordEntry *next;
90
91 /**
92 * DLL
93 */
94 struct CredentialRecordEntry *prev;
95
96 /**
97 * Number of references in delegation chains
98 */
99 uint32_t refcount;
100
101 /**
102 * Payload
103 */
104 struct GNUNET_CREDENTIAL_Credential *credential;
105};
106
107/**
108 * DLL used for delegations
109 * Used for OR delegations
110 */
111struct DelegationQueueEntry
112{
113 /**
114 * DLL
115 */
116 struct DelegationQueueEntry *next;
117
118 /**
119 * DLL
120 */
121 struct DelegationQueueEntry *prev;
122
123 /**
124 * Sets under this Queue
125 */
126 struct DelegationSetQueueEntry *set_entries_head;
127
128 /**
129 * Sets under this Queue
130 */
131 struct DelegationSetQueueEntry *set_entries_tail;
132
133 /**
134 * Parent set
135 */
136 struct DelegationSetQueueEntry *parent_set;
137
138 /**
139 * Required solutions
140 */
141 uint32_t required_solutions;
142};
143
144/**
145 * DLL for delegation sets
146 * Used for AND delegation set
147 */
148struct DelegationSetQueueEntry
149{
150 /**
151 * DLL
152 */
153 struct DelegationSetQueueEntry *next;
154
155 /**
156 * DLL
157 */
158 struct DelegationSetQueueEntry *prev;
159
160 /**
161 * GNS handle
162 */
163 struct GNUNET_GNS_LookupRequest *lookup_request;
164
165 /**
166 * Verify handle
167 */
168 struct VerifyRequestHandle *handle;
169
170 /**
171 * Parent attribute delegation
172 */
173 struct DelegationQueueEntry *parent;
174
175 /**
176 * Issuer key
177 */
178 struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key;
179
180 /**
181 * Queue entries of this set
182 */
183 struct DelegationQueueEntry *queue_entries_head;
184
185 /**
186 * Queue entries of this set
187 */
188 struct DelegationQueueEntry *queue_entries_tail;
189
190 /**
191 * Parent QueueEntry
192 */
193 struct DelegationQueueEntry *parent_queue_entry;
194
195 /**
196 * Issuer attribute delegated to
197 */
198 char *issuer_attribute;
199
200 /**
201 * The current attribute to look up
202 */
203 char *lookup_attribute;
204
205 /**
206 * Trailing attribute context
207 */
208 char *attr_trailer;
209
210 /**
211 * Still to resolve delegation as string
212 */
213 char *unresolved_attribute_delegation;
214
215 /**
216 * The delegation chain entry
217 */
218 struct DelegationChainEntry *delegation_chain_entry;
219
220};
221
222
223/**
224 * Handle to a lookup operation from api
225 */
226struct VerifyRequestHandle
227{
228
229 /**
230 * We keep these in a DLL.
231 */
232 struct VerifyRequestHandle *next;
233
234 /**
235 * We keep these in a DLL.
236 */
237 struct VerifyRequestHandle *prev;
238
239 /**
240 * Handle to the requesting client
241 */
242 struct GNUNET_SERVICE_Client *client;
243
244 /**
245 * GNS handle
246 */
247 struct GNUNET_GNS_LookupRequest *lookup_request;
248
249 /**
250 * Size of delegation tree
251 */
252 uint32_t delegation_chain_size;
253
254 /**
255 * Children of this attribute
256 */
257 struct DelegationChainEntry *delegation_chain_head;
258
259 /**
260 * Children of this attribute
261 */
262 struct DelegationChainEntry *delegation_chain_tail;
263
264 /**
265 * Issuer public key
266 */
267 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
268
269 /**
270 * Issuer attribute
271 */
272 char *issuer_attribute;
273
274 /**
275 * Subject public key
276 */
277 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
278
279 /**
280 * Credential DLL
281 */
282 struct CredentialRecordEntry *cred_chain_head;
283
284 /**
285 * Credential DLL
286 */
287 struct CredentialRecordEntry *cred_chain_tail;
288
289 /**
290 * Credential DLL size
291 */
292 uint32_t cred_chain_size;
293
294 /**
295 * Root Delegation Set
296 */
297 struct DelegationSetQueueEntry *root_set;
298
299 /**
300 * Current Delegation Pointer
301 */
302 struct DelegationQueueEntry *current_delegation;
303
304 /**
305 * request id
306 */
307 uint32_t request_id;
308
309 /**
310 * Pending lookups
311 */
312 uint64_t pending_lookups;
313
314 /**
315 * Credential iterator
316 */
317 struct GNUNET_NAMESTORE_ZoneIterator *cred_collection_iter;
318
319 /**
320 * Collect task
321 */
322 struct GNUNET_SCHEDULER_Task *collect_next_task;
323
324};
325
326
327/**
328 * Head of the DLL.
329 */
330static struct VerifyRequestHandle *vrh_head;
331
332/**
333 * Tail of the DLL.
334 */
335static struct VerifyRequestHandle *vrh_tail;
336
337/**
338 * Handle to the statistics service
339 */
340static struct GNUNET_STATISTICS_Handle *statistics;
341
342/**
343 * Handle to GNS service.
344 */
345static struct GNUNET_GNS_Handle *gns;
346
347
348/**
349 * Handle to namestore service
350 */
351static struct GNUNET_NAMESTORE_Handle *namestore;
352
353static void
354cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry)
355{
356 struct DelegationQueueEntry *dq_entry;
357 struct DelegationSetQueueEntry *child;
358
359 if (NULL == ds_entry)
360 return;
361
362 for (dq_entry = ds_entry->queue_entries_head;
363 NULL != dq_entry;
364 dq_entry = ds_entry->queue_entries_head)
365 {
366 GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
367 ds_entry->queue_entries_tail,
368 dq_entry);
369 for (child = dq_entry->set_entries_head;
370 NULL != child;
371 child = dq_entry->set_entries_head)
372 {
373 GNUNET_CONTAINER_DLL_remove (dq_entry->set_entries_head,
374 dq_entry->set_entries_tail,
375 child);
376 cleanup_delegation_set (child);
377 }
378 GNUNET_free (dq_entry);
379 }
380 GNUNET_free_non_null (ds_entry->issuer_key);
381 GNUNET_free_non_null (ds_entry->lookup_attribute);
382 GNUNET_free_non_null (ds_entry->issuer_attribute);
383 GNUNET_free_non_null (ds_entry->unresolved_attribute_delegation);
384 GNUNET_free_non_null (ds_entry->attr_trailer);
385 if (NULL != ds_entry->lookup_request)
386 {
387 GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
388 ds_entry->lookup_request = NULL;
389 }
390 if (NULL != ds_entry->delegation_chain_entry)
391 {
392 GNUNET_free_non_null (ds_entry->delegation_chain_entry->subject_attribute);
393 GNUNET_free_non_null (ds_entry->delegation_chain_entry->issuer_attribute);
394 GNUNET_free (ds_entry->delegation_chain_entry);
395 }
396 GNUNET_free (ds_entry);
397}
398
399static void
400cleanup_handle (struct VerifyRequestHandle *vrh)
401{
402 struct CredentialRecordEntry *cr_entry;
403 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
404 "Cleaning up...\n");
405 if (NULL != vrh->lookup_request)
406 {
407 GNUNET_GNS_lookup_cancel (vrh->lookup_request);
408 vrh->lookup_request = NULL;
409 }
410 cleanup_delegation_set (vrh->root_set);
411 GNUNET_free_non_null (vrh->issuer_attribute);
412 for (cr_entry = vrh->cred_chain_head;
413 NULL != vrh->cred_chain_head;
414 cr_entry = vrh->cred_chain_head)
415 {
416 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
417 vrh->cred_chain_tail,
418 cr_entry);
419 GNUNET_free_non_null (cr_entry->credential);
420 GNUNET_free (cr_entry);
421 }
422 GNUNET_free (vrh);
423}
424
425static void
426shutdown_task (void *cls)
427{
428 struct VerifyRequestHandle *vrh;
429
430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
431 "Shutting down!\n");
432
433 while (NULL != (vrh = vrh_head))
434 {
435 //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
436 GNUNET_CONTAINER_DLL_remove (vrh_head,
437 vrh_tail,
438 vrh);
439 cleanup_handle (vrh);
440 }
441
442 if (NULL != gns)
443 {
444 GNUNET_GNS_disconnect (gns);
445 gns = NULL;
446 }
447 if (NULL != namestore)
448 {
449 GNUNET_NAMESTORE_disconnect (namestore);
450 namestore = NULL;
451 }
452 if (NULL != statistics)
453 {
454 GNUNET_STATISTICS_destroy (statistics,
455 GNUNET_NO);
456 statistics = NULL;
457 }
458
459}
460
461
462
463static void
464send_lookup_response (struct VerifyRequestHandle *vrh)
465{
466 struct GNUNET_MQ_Envelope *env;
467 struct DelegationChainResultMessage *rmsg;
468 struct DelegationChainEntry *dce;
469 struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
470 struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
471 struct CredentialRecordEntry *cd;
472 struct CredentialRecordEntry *tmp;
473 size_t size;
474
475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
476 "Sending response\n");
477 dce = vrh->delegation_chain_head;
478 for (uint32_t i=0;i<vrh->delegation_chain_size;i++)
479 {
480 dd[i].issuer_key = dce->issuer_key;
481 dd[i].subject_key = dce->subject_key;
482 dd[i].issuer_attribute = dce->issuer_attribute;
483 dd[i].issuer_attribute_len = strlen (dce->issuer_attribute)+1;
484 dd[i].subject_attribute_len = 0;
485 dd[i].subject_attribute = NULL;
486 if (NULL != dce->subject_attribute)
487 {
488 dd[i].subject_attribute = dce->subject_attribute;
489 dd[i].subject_attribute_len = strlen(dce->subject_attribute)+1;
490 }
491 dce = dce->next;
492 }
493
494 /**
495 * Remove all credentials not needed
496 */
497 for (cd = vrh->cred_chain_head; NULL != cd;)
498 {
499 if (cd->refcount > 0)
500 {
501 cd = cd->next;
502 continue;
503 }
504 tmp = cd;
505 cd = cd->next;
506 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
507 vrh->cred_chain_tail,
508 tmp);
509 GNUNET_free (tmp->credential);
510 GNUNET_free (tmp);
511 vrh->cred_chain_size--;
512 }
513
514 /**
515 * Get serialized record data
516 * Append at the end of rmsg
517 */
518 cd = vrh->cred_chain_head;
519 for (uint32_t i=0;i<vrh->cred_chain_size;i++)
520 {
521 cred[i].issuer_key = cd->credential->issuer_key;
522 cred[i].subject_key = cd->credential->subject_key;
523 cred[i].issuer_attribute_len = strlen(cd->credential->issuer_attribute)+1;
524 cred[i].issuer_attribute = cd->credential->issuer_attribute;
525 cred[i].expiration = cd->credential->expiration;
526 cred[i].signature = cd->credential->signature;
527 cd = cd->next;
528 }
529 size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->delegation_chain_size,
530 dd,
531 vrh->cred_chain_size,
532 cred);
533 env = GNUNET_MQ_msg_extra (rmsg,
534 size,
535 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
536 //Assign id so that client can find associated request
537 rmsg->id = vrh->request_id;
538 rmsg->d_count = htonl (vrh->delegation_chain_size);
539 rmsg->c_count = htonl (vrh->cred_chain_size);
540
541 if (0 < vrh->cred_chain_size)
542 rmsg->cred_found = htonl (GNUNET_YES);
543 else
544 rmsg->cred_found = htonl (GNUNET_NO);
545
546 GNUNET_assert (-1 !=
547 GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->delegation_chain_size,
548 dd,
549 vrh->cred_chain_size,
550 cred,
551 size,
552 (char*)&rmsg[1]));
553
554 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client),
555 env);
556 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
557 cleanup_handle(vrh);
558
559 GNUNET_STATISTICS_update (statistics,
560 "Completed verifications", 1,
561 GNUNET_NO);
562}
563
564
565static void
566backward_resolution (void* cls,
567 uint32_t rd_count,
568 const struct GNUNET_GNSRECORD_Data *rd)
569{
570
571 struct VerifyRequestHandle *vrh;
572 const struct GNUNET_CREDENTIAL_DelegationRecord *sets;
573 struct CredentialRecordEntry *cred_pointer;
574 struct DelegationSetQueueEntry *current_set;
575 struct DelegationSetQueueEntry *ds_entry;
576 struct DelegationSetQueueEntry *tmp_set;
577 struct DelegationQueueEntry *dq_entry;
578 char *expanded_attr;
579 char *lookup_attribute;
580
581
582 current_set = cls;
583 current_set->lookup_request = NULL;
584 vrh = current_set->handle;
585 vrh->pending_lookups--;
586 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
587 "Got %d attrs\n", rd_count);
588
589 // Each OR
590 for (uint32_t i=0; i < rd_count; i++)
591 {
592 if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
593 continue;
594
595 sets = rd[i].data;
596 struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)];
597 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
598 "Found new attribute delegation with %d sets. Creating new Job...\n",
599 ntohl (sets->set_count));
600
601 if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size),
602 (const char*)&sets[1],
603 ntohl(sets->set_count),
604 set))
605 {
606 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
607 "Failed to deserialize!\n");
608 continue;
609 }
610 dq_entry = GNUNET_new (struct DelegationQueueEntry);
611 dq_entry->required_solutions = ntohl(sets->set_count);
612 dq_entry->parent_set = current_set;
613 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
614 current_set->queue_entries_tail,
615 dq_entry);
616 // Each AND
617 for (uint32_t j=0; j<ntohl(sets->set_count); j++)
618 {
619 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
620 if (NULL != current_set->attr_trailer)
621 {
622 if (0 == set[j].subject_attribute_len)
623 {
624 GNUNET_asprintf (&expanded_attr,
625 "%s",
626 current_set->attr_trailer);
627
628 } else {
629 GNUNET_asprintf (&expanded_attr,
630 "%s.%s",
631 set[j].subject_attribute,
632 current_set->attr_trailer);
633 }
634 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
635 "Expanded to %s\n", expanded_attr);
636 ds_entry->unresolved_attribute_delegation = expanded_attr;
637 } else {
638 if (0 != set[j].subject_attribute_len)
639 {
640 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
641 "Not Expanding %s\n", set[j].subject_attribute);
642 ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute);
643 }
644 }
645
646 //Add a credential chain entry
647 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
648 ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
649 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
650 GNUNET_memcpy (ds_entry->issuer_key,
651 &set[j].subject_key,
652 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
653 if (0 < set[j].subject_attribute_len)
654 ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute);
655 ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
656 ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute);
657
658 ds_entry->parent_queue_entry = dq_entry; //current_delegation;
659 GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head,
660 dq_entry->set_entries_tail,
661 ds_entry);
662
663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
664 "Checking for cred match\n");
665 /**
666 * Check if this delegation already matches one of our credentials
667 */
668 for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL;
669 cred_pointer = cred_pointer->next)
670 {
671 if(0 != memcmp (&set->subject_key,
672 &cred_pointer->credential->issuer_key,
673 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
674 continue;
675 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
676 "Checking if %s matches %s\n",
677 ds_entry->unresolved_attribute_delegation,
678 cred_pointer->credential->issuer_attribute);
679
680 if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
681 cred_pointer->credential->issuer_attribute))
682 continue;
683
684 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
685 "Found issuer\n");
686 cred_pointer->refcount++;
687 //Backtrack
688 for (tmp_set = ds_entry;
689 NULL != tmp_set->parent_queue_entry;
690 tmp_set = tmp_set->parent_queue_entry->parent_set)
691 {
692 tmp_set->parent_queue_entry->required_solutions--;
693 if (NULL != tmp_set->delegation_chain_entry)
694 {
695 vrh->delegation_chain_size++;
696 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
697 vrh->delegation_chain_tail,
698 tmp_set->delegation_chain_entry);
699 }
700 if (0 < tmp_set->parent_queue_entry->required_solutions)
701 break;
702 }
703
704 if (NULL == tmp_set->parent_queue_entry)
705 {
706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
707 "All solutions found\n");
708 //Found match
709 send_lookup_response (vrh);
710 return;
711 }
712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
713 "Not all solutions found yet.\n");
714 continue;
715
716 }
717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
718 "Building new lookup request from %s\n",
719 ds_entry->unresolved_attribute_delegation);
720 //Continue with backward resolution
721 char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1];
722 strcpy (issuer_attribute_name,
723 ds_entry->unresolved_attribute_delegation);
724 char *next_attr = strtok (issuer_attribute_name, ".");
725 GNUNET_asprintf (&lookup_attribute,
726 "%s.gnu",
727 next_attr);
728 GNUNET_asprintf (&ds_entry->lookup_attribute,
729 "%s",
730 next_attr);
731 if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation))
732 {
733 ds_entry->attr_trailer = NULL;
734 } else {
735 next_attr += strlen (next_attr) + 1;
736 ds_entry->attr_trailer = GNUNET_strdup (next_attr);
737 }
738
739 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
740 "Looking up %s\n", ds_entry->lookup_attribute);
741 if (NULL != ds_entry->attr_trailer)
742 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
743 "%s still to go...\n", ds_entry->attr_trailer);
744
745 vrh->pending_lookups++;
746 ds_entry->handle = vrh;
747 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
748 lookup_attribute,
749 ds_entry->issuer_key, //issuer_key,
750 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
751 GNUNET_GNS_LO_DEFAULT,
752 &backward_resolution,
753 ds_entry);
754 GNUNET_free (lookup_attribute);
755 }
756 }
757
758 if(0 == vrh->pending_lookups)
759 {
760 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
761 "We are all out of attributes...\n");
762 send_lookup_response (vrh);
763 return;
764
765 }
766}
767
768
769/**
770 * Result from GNS lookup.
771 *
772 * @param cls the closure (our client lookup handle)
773 */
774static void
775delegation_chain_resolution_start (void* cls)
776{
777 struct VerifyRequestHandle *vrh = cls;
778 struct DelegationSetQueueEntry *ds_entry;
779 struct CredentialRecordEntry *cr_entry;
780 vrh->lookup_request = NULL;
781
782 if (0 == vrh->cred_chain_size)
783 {
784 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
785 "No credentials found\n");
786 send_lookup_response (vrh);
787 return;
788 }
789
790 for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = cr_entry->next)
791 {
792 if (0 != memcmp (&cr_entry->credential->issuer_key,
793 &vrh->issuer_key,
794 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
795 continue;
796 if (0 != strcmp (cr_entry->credential->issuer_attribute, vrh->issuer_attribute))
797 continue;
798 cr_entry->refcount++;
799 //Found match prematurely
800 send_lookup_response (vrh);
801 return;
802
803 }
804
805 /**
806 * Check for attributes from the issuer and follow the chain
807 * till you get the required subject's attributes
808 */
809 char issuer_attribute_name[strlen (vrh->issuer_attribute)];
810 strcpy (issuer_attribute_name,
811 vrh->issuer_attribute);
812 strcpy (issuer_attribute_name + strlen (vrh->issuer_attribute),
813 ".gnu");
814 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
815 "Looking up %s\n", issuer_attribute_name);
816 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
817 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
818 memcpy (ds_entry->issuer_key,
819 &vrh->issuer_key,
820 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
821 ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
822 ds_entry->handle = vrh;
823 ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
824 vrh->root_set = ds_entry;
825 vrh->pending_lookups = 1;
826 //Start with backward resolution
827 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
828 issuer_attribute_name,
829 &vrh->issuer_key, //issuer_key,
830 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
831 GNUNET_GNS_LO_DEFAULT,
832 &backward_resolution,
833 ds_entry);
834}
835
836static int
837check_verify (void *cls,
838 const struct VerifyMessage *v_msg)
839{
840 size_t msg_size;
841 const char* attr;
842
843 msg_size = ntohs (v_msg->header.size);
844 if (msg_size < sizeof (struct VerifyMessage))
845 {
846 GNUNET_break (0);
847 return GNUNET_SYSERR;
848 }
849 if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
850 {
851 GNUNET_break (0);
852 return GNUNET_SYSERR;
853 }
854 attr = (const char *) &v_msg[1];
855
856 if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH)
857 {
858 GNUNET_break (0);
859 return GNUNET_SYSERR;
860 }
861 return GNUNET_OK;
862}
863
864static void
865handle_verify (void *cls,
866 const struct VerifyMessage *v_msg)
867{
868 struct VerifyRequestHandle *vrh;
869 struct GNUNET_SERVICE_Client *client = cls;
870 struct CredentialRecordEntry *cr_entry;
871 uint32_t credentials_count;
872 uint32_t credential_data_size;
873 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
874 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
875 char *attrptr = attr;
876 char *credential_data;
877 const char *utf_in;
878
879 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
880 "Received VERIFY message\n");
881 utf_in = (const char *) &v_msg[1];
882 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
883 GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
884 issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
885 vrh = GNUNET_new (struct VerifyRequestHandle);
886 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
887 vrh->client = client;
888 vrh->request_id = v_msg->id;
889 vrh->issuer_key = v_msg->issuer_key;
890 vrh->subject_key = v_msg->subject_key;
891 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
892 if (NULL == issuer_attribute)
893 {
894 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
895 "No issuer attribute provided!\n");
896 send_lookup_response (vrh);
897 return;
898 }
899 /**
900 * First, collect credentials
901 * TODO: cleanup!
902 */
903 credentials_count = ntohl(v_msg->c_count);
904 credential_data_size = ntohs (v_msg->header.size)
905 - sizeof (struct VerifyMessage)
906 - ntohs (v_msg->issuer_attribute_len)
907 - 1;
908 struct GNUNET_CREDENTIAL_Credential credentials[credentials_count];
909 credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
910 if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize (credential_data_size,
911 credential_data,
912 credentials_count,
913 credentials))
914 {
915 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
916 "Cannot deserialize credentials!\n");
917 send_lookup_response (vrh);
918 return;
919 }
920
921 for (uint32_t i=0;i<credentials_count;i++) {
922 cr_entry = GNUNET_new (struct CredentialRecordEntry);
923 cr_entry->credential = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) +
924 credentials[i].issuer_attribute_len);
925 GNUNET_memcpy (cr_entry->credential,
926 &credentials[i],
927 sizeof (struct GNUNET_CREDENTIAL_Credential));
928 GNUNET_memcpy (&cr_entry->credential[1],
929 credentials[i].issuer_attribute,
930 credentials[i].issuer_attribute_len);
931 cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1];
932 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
933 vrh->cred_chain_tail,
934 cr_entry);
935 vrh->cred_chain_size++;
936 }
937
938 delegation_chain_resolution_start (vrh);
939
940}
941
942static void
943handle_cred_collection_error_cb (void *cls)
944{
945 struct VerifyRequestHandle *vrh = cls;
946 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
947 "Got disconnected from namestore database.\n");
948 vrh->cred_collection_iter = NULL;
949 send_lookup_response (vrh);
950}
951
952static void
953collect_next (void *cls)
954{
955 struct VerifyRequestHandle *vrh = cls;
956 vrh->collect_next_task = NULL;
957 GNUNET_assert (NULL != vrh->cred_collection_iter);
958 GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter);
959}
960
961static void
962handle_cred_collection_cb (void *cls,
963 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
964 const char *label,
965 unsigned int rd_count,
966 const struct GNUNET_GNSRECORD_Data *rd)
967{
968 struct VerifyRequestHandle *vrh = cls;
969 struct GNUNET_CREDENTIAL_Credential *crd;
970 struct CredentialRecordEntry *cr_entry;
971 int cred_record_count;
972
973 cred_record_count = 0;
974 for (uint32_t i=0; i < rd_count; i++)
975 {
976 if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
977 continue;
978 cred_record_count++;
979 crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
980 rd[i].data_size);
981 if (NULL == crd)
982 {
983 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
984 "Invalid credential found\n");
985 continue;
986 }
987 cr_entry = GNUNET_new (struct CredentialRecordEntry);
988 cr_entry->credential = crd;
989 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
990 vrh->cred_chain_tail,
991 cr_entry);
992 vrh->cred_chain_size++;
993 }
994 vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next,
995 vrh);
996}
997
998static void
999handle_cred_collection_finished_cb (void *cls)
1000{
1001 struct VerifyRequestHandle *vrh = cls;
1002 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1003 "Done collecting credentials.\n");
1004 vrh->cred_collection_iter = NULL;
1005 delegation_chain_resolution_start (vrh);
1006}
1007
1008static void
1009handle_collect (void *cls,
1010 const struct CollectMessage *c_msg)
1011{
1012 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1013 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1014 struct VerifyRequestHandle *vrh;
1015 struct GNUNET_SERVICE_Client *client = cls;
1016 char *attrptr = attr;
1017 const char *utf_in;
1018
1019 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1020 "Received COLLECT message\n");
1021
1022 utf_in = (const char *) &c_msg[1];
1023 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
1024
1025 GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
1026 issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
1027 vrh = GNUNET_new (struct VerifyRequestHandle);
1028 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
1029 vrh->client = client;
1030 vrh->request_id = c_msg->id;
1031 vrh->issuer_key = c_msg->issuer_key;
1032 GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key,
1033 &vrh->subject_key);
1034 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
1035
1036 if (NULL == issuer_attribute)
1037 {
1038 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1039 "No issuer attribute provided!\n");
1040 send_lookup_response (vrh);
1041 return;
1042 }
1043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1044 "Getting credentials for subject\n");
1045 /**
1046 * First, get attribute from subject
1047 */
1048 vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore,
1049 &c_msg->subject_key,
1050 &handle_cred_collection_error_cb,
1051 vrh,
1052 &handle_cred_collection_cb,
1053 vrh,
1054 &handle_cred_collection_finished_cb,
1055 vrh);
1056}
1057
1058
1059static int
1060check_collect (void *cls,
1061 const struct CollectMessage *c_msg)
1062{
1063 size_t msg_size;
1064 const char* attr;
1065
1066 msg_size = ntohs (c_msg->header.size);
1067 if (msg_size < sizeof (struct CollectMessage))
1068 {
1069 GNUNET_break (0);
1070 return GNUNET_SYSERR;
1071 }
1072 if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
1073 {
1074 GNUNET_break (0);
1075 return GNUNET_SYSERR;
1076 }
1077 attr = (const char *) &c_msg[1];
1078
1079 if ( ('\0' != attr[ntohs(c_msg->header.size) - sizeof (struct CollectMessage) - 1]) ||
1080 (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
1081 {
1082 GNUNET_break (0);
1083 return GNUNET_SYSERR;
1084 }
1085 return GNUNET_OK;
1086}
1087
1088static void
1089client_disconnect_cb (void *cls,
1090 struct GNUNET_SERVICE_Client *client,
1091 void *app_ctx)
1092{
1093 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1094 "Client %p disconnected\n",
1095 client);
1096}
1097
1098static void *
1099client_connect_cb (void *cls,
1100 struct GNUNET_SERVICE_Client *client,
1101 struct GNUNET_MQ_Handle *mq)
1102{
1103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1104 "Client %p connected\n",
1105 client);
1106 return client;
1107}
1108
1109/**
1110 * Process Credential requests.
1111 *
1112 * @param cls closure
1113 * @param c configuration to use
1114 * @param handle service handle
1115 */
1116static void
1117run (void *cls,
1118 const struct GNUNET_CONFIGURATION_Handle *c,
1119 struct GNUNET_SERVICE_Handle *handle)
1120{
1121
1122 gns = GNUNET_GNS_connect (c);
1123 if (NULL == gns)
1124 {
1125 fprintf (stderr,
1126 _("Failed to connect to GNS\n"));
1127 }
1128 namestore = GNUNET_NAMESTORE_connect (c);
1129 if (NULL == namestore)
1130 {
1131 fprintf (stderr,
1132 _("Failed to connect to namestore\n"));
1133 }
1134
1135 statistics = GNUNET_STATISTICS_create ("credential", c);
1136 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1137}
1138
1139
1140/**
1141 * Define "main" method using service macro
1142 */
1143GNUNET_SERVICE_MAIN
1144("credential",
1145 GNUNET_SERVICE_OPTION_NONE,
1146 &run,
1147 &client_connect_cb,
1148 &client_disconnect_cb,
1149 NULL,
1150 GNUNET_MQ_hd_var_size (verify,
1151 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
1152 struct VerifyMessage,
1153 NULL),
1154 GNUNET_MQ_hd_var_size (collect,
1155 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT,
1156 struct CollectMessage,
1157 NULL),
1158 GNUNET_MQ_handler_end());
1159
1160/* end of gnunet-service-credential.c */