2 This file is part of GNUnet.
3 Copyright (C) 2011-2013 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
16 * @file credential/gnunet-service-credential.c
17 * @brief GNUnet Credential Service (main service)
18 * @author Martin Schanzenbach
21 #include "gnunet_util_lib.h"
22 #include "gnunet_credential_service.h"
23 #include "gnunet_statistics_service.h"
24 #include "credential.h"
25 #include "credential_serialization.h"
26 #include "gnunet_protocols.h"
27 #include "gnunet_signatures.h"
29 #include <gnunet_dnsparser_lib.h>
30 #include <gnunet_identity_service.h>
31 #include <gnunet_gnsrecord_lib.h>
32 #include <gnunet_namestore_service.h>
33 #include <gnunet_gns_service.h>
36 #define GNUNET_CREDENTIAL_MAX_LENGTH 255
38 struct VerifyRequestHandle;
40 struct DelegationSetQueueEntry;
43 struct DelegationChainEntry
48 struct DelegationChainEntry *next;
53 struct DelegationChainEntry *prev;
58 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
63 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
66 * The issued attribute
68 char *issuer_attribute;
71 * The delegated attribute
73 char *subject_attribute;
79 struct CredentialRecordEntry
84 struct CredentialRecordEntry *next;
89 struct CredentialRecordEntry *prev;
92 * Number of references in delegation chains
99 struct GNUNET_CREDENTIAL_Credential *credential;
103 * DLL used for delegations
104 * Used for OR delegations
106 struct DelegationQueueEntry
111 struct DelegationQueueEntry *next;
116 struct DelegationQueueEntry *prev;
119 * Sets under this Queue
121 struct DelegationSetQueueEntry *set_entries_head;
124 * Sets under this Queue
126 struct DelegationSetQueueEntry *set_entries_tail;
131 struct DelegationSetQueueEntry *parent_set;
136 uint32_t required_solutions;
140 * DLL for delegation sets
141 * Used for AND delegation set
143 struct DelegationSetQueueEntry
148 struct DelegationSetQueueEntry *next;
153 struct DelegationSetQueueEntry *prev;
158 struct GNUNET_GNS_LookupRequest *lookup_request;
163 struct VerifyRequestHandle *handle;
166 * Parent attribute delegation
168 struct DelegationQueueEntry *parent;
173 struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key;
176 * Queue entries of this set
178 struct DelegationQueueEntry *queue_entries_head;
181 * Queue entries of this set
183 struct DelegationQueueEntry *queue_entries_tail;
188 struct DelegationQueueEntry *parent_queue_entry;
191 * Issuer attribute delegated to
193 char *issuer_attribute;
196 * The current attribute to look up
198 char *lookup_attribute;
201 * Trailing attribute context
206 * Still to resolve delegation as string
208 char *unresolved_attribute_delegation;
211 * The delegation chain entry
213 struct DelegationChainEntry *delegation_chain_entry;
219 * Handle to a lookup operation from api
221 struct VerifyRequestHandle
225 * We keep these in a DLL.
227 struct VerifyRequestHandle *next;
230 * We keep these in a DLL.
232 struct VerifyRequestHandle *prev;
235 * Handle to the requesting client
237 struct GNUNET_SERVICE_Client *client;
242 struct GNUNET_GNS_LookupRequest *lookup_request;
245 * Size of delegation tree
247 uint32_t delegation_chain_size;
250 * Children of this attribute
252 struct DelegationChainEntry *delegation_chain_head;
255 * Children of this attribute
257 struct DelegationChainEntry *delegation_chain_tail;
262 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
267 char *issuer_attribute;
272 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
277 struct CredentialRecordEntry *cred_chain_head;
282 struct CredentialRecordEntry *cred_chain_tail;
285 * Credential DLL size
287 uint32_t cred_chain_size;
290 * Root Delegation Set
292 struct DelegationSetQueueEntry *root_set;
295 * Current Delegation Pointer
297 struct DelegationQueueEntry *current_delegation;
307 uint64_t pending_lookups;
310 * Credential iterator
312 struct GNUNET_NAMESTORE_ZoneIterator *cred_collection_iter;
317 struct GNUNET_SCHEDULER_Task *collect_next_task;
325 static struct VerifyRequestHandle *vrh_head;
330 static struct VerifyRequestHandle *vrh_tail;
333 * Handle to the statistics service
335 static struct GNUNET_STATISTICS_Handle *statistics;
338 * Handle to GNS service.
340 static struct GNUNET_GNS_Handle *gns;
344 * Handle to namestore service
346 static struct GNUNET_NAMESTORE_Handle *namestore;
349 cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry)
351 struct DelegationQueueEntry *dq_entry;
352 struct DelegationSetQueueEntry *child;
354 if (NULL == ds_entry)
357 for (dq_entry = ds_entry->queue_entries_head;
359 dq_entry = ds_entry->queue_entries_head)
361 GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
362 ds_entry->queue_entries_tail,
364 for (child = dq_entry->set_entries_head;
366 child = dq_entry->set_entries_head)
368 GNUNET_CONTAINER_DLL_remove (dq_entry->set_entries_head,
369 dq_entry->set_entries_tail,
371 cleanup_delegation_set (child);
373 GNUNET_free (dq_entry);
375 GNUNET_free_non_null (ds_entry->issuer_key);
376 GNUNET_free_non_null (ds_entry->lookup_attribute);
377 GNUNET_free_non_null (ds_entry->issuer_attribute);
378 GNUNET_free_non_null (ds_entry->unresolved_attribute_delegation);
379 GNUNET_free_non_null (ds_entry->attr_trailer);
380 if (NULL != ds_entry->lookup_request)
382 GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
383 ds_entry->lookup_request = NULL;
385 if (NULL != ds_entry->delegation_chain_entry)
387 GNUNET_free_non_null (ds_entry->delegation_chain_entry->subject_attribute);
388 GNUNET_free_non_null (ds_entry->delegation_chain_entry->issuer_attribute);
389 GNUNET_free (ds_entry->delegation_chain_entry);
391 GNUNET_free (ds_entry);
395 cleanup_handle (struct VerifyRequestHandle *vrh)
397 struct CredentialRecordEntry *cr_entry;
398 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
400 if (NULL != vrh->lookup_request)
402 GNUNET_GNS_lookup_cancel (vrh->lookup_request);
403 vrh->lookup_request = NULL;
405 cleanup_delegation_set (vrh->root_set);
406 GNUNET_free_non_null (vrh->issuer_attribute);
407 for (cr_entry = vrh->cred_chain_head;
408 NULL != vrh->cred_chain_head;
409 cr_entry = vrh->cred_chain_head)
411 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
412 vrh->cred_chain_tail,
414 GNUNET_free_non_null (cr_entry->credential);
415 GNUNET_free (cr_entry);
421 shutdown_task (void *cls)
423 struct VerifyRequestHandle *vrh;
425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
428 while (NULL != (vrh = vrh_head))
430 //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
431 GNUNET_CONTAINER_DLL_remove (vrh_head,
434 cleanup_handle (vrh);
439 GNUNET_GNS_disconnect (gns);
442 if (NULL != namestore)
444 GNUNET_NAMESTORE_disconnect (namestore);
447 if (NULL != statistics)
449 GNUNET_STATISTICS_destroy (statistics,
459 send_lookup_response (struct VerifyRequestHandle *vrh)
461 struct GNUNET_MQ_Envelope *env;
462 struct DelegationChainResultMessage *rmsg;
463 struct DelegationChainEntry *dce;
464 struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
465 struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
466 struct CredentialRecordEntry *cd;
467 struct CredentialRecordEntry *tmp;
470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
471 "Sending response\n");
472 dce = vrh->delegation_chain_head;
473 for (uint32_t i=0;i<vrh->delegation_chain_size;i++)
475 dd[i].issuer_key = dce->issuer_key;
476 dd[i].subject_key = dce->subject_key;
477 dd[i].issuer_attribute = dce->issuer_attribute;
478 dd[i].issuer_attribute_len = strlen (dce->issuer_attribute)+1;
479 dd[i].subject_attribute_len = 0;
480 dd[i].subject_attribute = NULL;
481 if (NULL != dce->subject_attribute)
483 dd[i].subject_attribute = dce->subject_attribute;
484 dd[i].subject_attribute_len = strlen(dce->subject_attribute)+1;
490 * Remove all credentials not needed
492 for (cd = vrh->cred_chain_head; NULL != cd;)
494 if (cd->refcount > 0)
501 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
502 vrh->cred_chain_tail,
504 GNUNET_free (tmp->credential);
506 vrh->cred_chain_size--;
510 * Get serialized record data
511 * Append at the end of rmsg
513 cd = vrh->cred_chain_head;
514 for (uint32_t i=0;i<vrh->cred_chain_size;i++)
516 cred[i].issuer_key = cd->credential->issuer_key;
517 cred[i].subject_key = cd->credential->subject_key;
518 cred[i].issuer_attribute_len = strlen(cd->credential->issuer_attribute)+1;
519 cred[i].issuer_attribute = cd->credential->issuer_attribute;
520 cred[i].expiration = cd->credential->expiration;
521 cred[i].signature = cd->credential->signature;
524 size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->delegation_chain_size,
526 vrh->cred_chain_size,
528 env = GNUNET_MQ_msg_extra (rmsg,
530 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
531 //Assign id so that client can find associated request
532 rmsg->id = vrh->request_id;
533 rmsg->d_count = htonl (vrh->delegation_chain_size);
534 rmsg->c_count = htonl (vrh->cred_chain_size);
536 if (0 < vrh->cred_chain_size)
537 rmsg->cred_found = htonl (GNUNET_YES);
539 rmsg->cred_found = htonl (GNUNET_NO);
542 GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->delegation_chain_size,
544 vrh->cred_chain_size,
549 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client),
551 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
554 GNUNET_STATISTICS_update (statistics,
555 "Completed verifications", 1,
561 backward_resolution (void* cls,
563 const struct GNUNET_GNSRECORD_Data *rd)
566 struct VerifyRequestHandle *vrh;
567 const struct GNUNET_CREDENTIAL_DelegationRecord *sets;
568 struct CredentialRecordEntry *cred_pointer;
569 struct DelegationSetQueueEntry *current_set;
570 struct DelegationSetQueueEntry *ds_entry;
571 struct DelegationSetQueueEntry *tmp_set;
572 struct DelegationQueueEntry *dq_entry;
574 char *lookup_attribute;
578 current_set->lookup_request = NULL;
579 vrh = current_set->handle;
580 vrh->pending_lookups--;
581 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
582 "Got %d attrs\n", rd_count);
585 for (uint32_t i=0; i < rd_count; i++)
587 if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
591 struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)];
592 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
593 "Found new attribute delegation with %d sets. Creating new Job...\n",
594 ntohl (sets->set_count));
596 if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size),
597 (const char*)&sets[1],
598 ntohl(sets->set_count),
601 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
602 "Failed to deserialize!\n");
605 dq_entry = GNUNET_new (struct DelegationQueueEntry);
606 dq_entry->required_solutions = ntohl(sets->set_count);
607 dq_entry->parent_set = current_set;
608 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
609 current_set->queue_entries_tail,
612 for (uint32_t j=0; j<ntohl(sets->set_count); j++)
614 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
615 if (NULL != current_set->attr_trailer)
617 if (0 == set[j].subject_attribute_len)
619 GNUNET_asprintf (&expanded_attr,
621 current_set->attr_trailer);
624 GNUNET_asprintf (&expanded_attr,
626 set[j].subject_attribute,
627 current_set->attr_trailer);
629 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
630 "Expanded to %s\n", expanded_attr);
631 ds_entry->unresolved_attribute_delegation = expanded_attr;
633 if (0 != set[j].subject_attribute_len)
635 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
636 "Not Expanding %s\n", set[j].subject_attribute);
637 ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute);
641 //Add a credential chain entry
642 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
643 ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
644 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
645 GNUNET_memcpy (ds_entry->issuer_key,
647 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
648 if (0 < set[j].subject_attribute_len)
649 ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute);
650 ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
651 ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute);
653 ds_entry->parent_queue_entry = dq_entry; //current_delegation;
654 GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head,
655 dq_entry->set_entries_tail,
658 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
659 "Checking for cred match\n");
661 * Check if this delegation already matches one of our credentials
663 for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL;
664 cred_pointer = cred_pointer->next)
666 if(0 != memcmp (&set->subject_key,
667 &cred_pointer->credential->issuer_key,
668 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
671 "Checking if %s matches %s\n",
672 ds_entry->unresolved_attribute_delegation,
673 cred_pointer->credential->issuer_attribute);
675 if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
676 cred_pointer->credential->issuer_attribute))
679 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
681 cred_pointer->refcount++;
683 for (tmp_set = ds_entry;
684 NULL != tmp_set->parent_queue_entry;
685 tmp_set = tmp_set->parent_queue_entry->parent_set)
687 tmp_set->parent_queue_entry->required_solutions--;
688 if (NULL != tmp_set->delegation_chain_entry)
690 vrh->delegation_chain_size++;
691 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
692 vrh->delegation_chain_tail,
693 tmp_set->delegation_chain_entry);
695 if (0 < tmp_set->parent_queue_entry->required_solutions)
699 if (NULL == tmp_set->parent_queue_entry)
701 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
702 "All solutions found\n");
704 send_lookup_response (vrh);
707 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
708 "Not all solutions found yet.\n");
712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
713 "Building new lookup request from %s\n",
714 ds_entry->unresolved_attribute_delegation);
715 //Continue with backward resolution
716 char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1];
717 strcpy (issuer_attribute_name,
718 ds_entry->unresolved_attribute_delegation);
719 char *next_attr = strtok (issuer_attribute_name, ".");
720 if (NULL == next_attr)
722 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
723 "Failed to parse next attribute\n");
726 GNUNET_asprintf (&lookup_attribute,
729 GNUNET_asprintf (&ds_entry->lookup_attribute,
732 if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation))
734 ds_entry->attr_trailer = NULL;
736 next_attr += strlen (next_attr) + 1;
737 ds_entry->attr_trailer = GNUNET_strdup (next_attr);
740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
741 "Looking up %s\n", ds_entry->lookup_attribute);
742 if (NULL != ds_entry->attr_trailer)
743 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
744 "%s still to go...\n", ds_entry->attr_trailer);
746 vrh->pending_lookups++;
747 ds_entry->handle = vrh;
748 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
750 ds_entry->issuer_key, //issuer_key,
751 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
752 GNUNET_GNS_LO_DEFAULT,
753 &backward_resolution,
755 GNUNET_free (lookup_attribute);
759 if(0 == vrh->pending_lookups)
761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
762 "We are all out of attributes...\n");
763 send_lookup_response (vrh);
771 * Result from GNS lookup.
773 * @param cls the closure (our client lookup handle)
776 delegation_chain_resolution_start (void* cls)
778 struct VerifyRequestHandle *vrh = cls;
779 struct DelegationSetQueueEntry *ds_entry;
780 struct CredentialRecordEntry *cr_entry;
781 vrh->lookup_request = NULL;
783 if (0 == vrh->cred_chain_size)
785 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
786 "No credentials found\n");
787 send_lookup_response (vrh);
791 for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = cr_entry->next)
793 if (0 != memcmp (&cr_entry->credential->issuer_key,
795 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
797 if (0 != strcmp (cr_entry->credential->issuer_attribute, vrh->issuer_attribute))
799 cr_entry->refcount++;
800 //Found match prematurely
801 send_lookup_response (vrh);
807 * Check for attributes from the issuer and follow the chain
808 * till you get the required subject's attributes
810 char issuer_attribute_name[strlen (vrh->issuer_attribute) + strlen (".gnu") + 1];
811 strcpy (issuer_attribute_name,
812 vrh->issuer_attribute);
813 strcpy (issuer_attribute_name + strlen (vrh->issuer_attribute),
815 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
816 "Looking up %s\n", issuer_attribute_name);
817 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
818 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
819 GNUNET_memcpy (ds_entry->issuer_key,
821 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
822 ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
823 ds_entry->handle = vrh;
824 ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
825 vrh->root_set = ds_entry;
826 vrh->pending_lookups = 1;
827 //Start with backward resolution
828 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
829 issuer_attribute_name,
830 &vrh->issuer_key, //issuer_key,
831 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
832 GNUNET_GNS_LO_DEFAULT,
833 &backward_resolution,
838 check_verify (void *cls,
839 const struct VerifyMessage *v_msg)
844 msg_size = ntohs (v_msg->header.size);
845 if (msg_size < sizeof (struct VerifyMessage))
848 return GNUNET_SYSERR;
850 if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
853 return GNUNET_SYSERR;
855 attr = (const char *) &v_msg[1];
857 if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH)
860 return GNUNET_SYSERR;
866 handle_verify (void *cls,
867 const struct VerifyMessage *v_msg)
869 struct VerifyRequestHandle *vrh;
870 struct GNUNET_SERVICE_Client *client = cls;
871 struct CredentialRecordEntry *cr_entry;
872 uint32_t credentials_count;
873 uint32_t credential_data_size;
874 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
875 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
876 char *attrptr = attr;
877 char *credential_data;
880 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
881 "Received VERIFY message\n");
882 utf_in = (const char *) &v_msg[1];
883 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
884 GNUNET_memcpy (issuer_attribute,
886 ntohs (v_msg->issuer_attribute_len));
887 issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
888 vrh = GNUNET_new (struct VerifyRequestHandle);
889 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
890 vrh->client = client;
891 vrh->request_id = v_msg->id;
892 vrh->issuer_key = v_msg->issuer_key;
893 vrh->subject_key = v_msg->subject_key;
894 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
895 if (0 == strlen (issuer_attribute))
897 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
898 "No issuer attribute provided!\n");
899 send_lookup_response (vrh);
903 * First, collect credentials
906 credentials_count = ntohl(v_msg->c_count);
907 credential_data_size = ntohs (v_msg->header.size)
908 - sizeof (struct VerifyMessage)
909 - ntohs (v_msg->issuer_attribute_len)
911 struct GNUNET_CREDENTIAL_Credential credentials[credentials_count];
912 credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
913 if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize (credential_data_size,
918 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
919 "Cannot deserialize credentials!\n");
920 send_lookup_response (vrh);
924 for (uint32_t i=0;i<credentials_count;i++) {
925 cr_entry = GNUNET_new (struct CredentialRecordEntry);
926 cr_entry->credential = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) +
927 credentials[i].issuer_attribute_len);
928 GNUNET_memcpy (cr_entry->credential,
930 sizeof (struct GNUNET_CREDENTIAL_Credential));
931 GNUNET_memcpy (&cr_entry->credential[1],
932 credentials[i].issuer_attribute,
933 credentials[i].issuer_attribute_len);
934 cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1];
935 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
936 vrh->cred_chain_tail,
938 vrh->cred_chain_size++;
941 delegation_chain_resolution_start (vrh);
946 handle_cred_collection_error_cb (void *cls)
948 struct VerifyRequestHandle *vrh = cls;
949 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
950 "Got disconnected from namestore database.\n");
951 vrh->cred_collection_iter = NULL;
952 send_lookup_response (vrh);
956 collect_next (void *cls)
958 struct VerifyRequestHandle *vrh = cls;
959 vrh->collect_next_task = NULL;
960 GNUNET_assert (NULL != vrh->cred_collection_iter);
961 GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter,
967 handle_cred_collection_cb (void *cls,
968 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
970 unsigned int rd_count,
971 const struct GNUNET_GNSRECORD_Data *rd)
973 struct VerifyRequestHandle *vrh = cls;
974 struct GNUNET_CREDENTIAL_Credential *crd;
975 struct CredentialRecordEntry *cr_entry;
976 int cred_record_count;
978 cred_record_count = 0;
979 for (uint32_t i=0; i < rd_count; i++)
981 if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
984 crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
988 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
989 "Invalid credential found\n");
992 cr_entry = GNUNET_new (struct CredentialRecordEntry);
993 cr_entry->credential = crd;
994 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
995 vrh->cred_chain_tail,
997 vrh->cred_chain_size++;
999 vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next,
1004 handle_cred_collection_finished_cb (void *cls)
1006 struct VerifyRequestHandle *vrh = cls;
1007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1008 "Done collecting credentials.\n");
1009 vrh->cred_collection_iter = NULL;
1010 delegation_chain_resolution_start (vrh);
1014 handle_collect (void *cls,
1015 const struct CollectMessage *c_msg)
1017 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1018 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1019 struct VerifyRequestHandle *vrh;
1020 struct GNUNET_SERVICE_Client *client = cls;
1021 char *attrptr = attr;
1024 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1025 "Received COLLECT message\n");
1027 utf_in = (const char *) &c_msg[1];
1028 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
1030 GNUNET_memcpy (issuer_attribute,
1032 ntohs (c_msg->issuer_attribute_len));
1033 issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
1034 vrh = GNUNET_new (struct VerifyRequestHandle);
1035 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
1036 vrh->client = client;
1037 vrh->request_id = c_msg->id;
1038 vrh->issuer_key = c_msg->issuer_key;
1039 GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key,
1041 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
1043 if (0 == strlen (issuer_attribute))
1045 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1046 "No issuer attribute provided!\n");
1047 send_lookup_response (vrh);
1050 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1051 "Getting credentials for subject\n");
1053 * First, get attribute from subject
1055 vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore,
1056 &c_msg->subject_key,
1057 &handle_cred_collection_error_cb,
1059 &handle_cred_collection_cb,
1061 &handle_cred_collection_finished_cb,
1067 check_collect (void *cls,
1068 const struct CollectMessage *c_msg)
1073 msg_size = ntohs (c_msg->header.size);
1074 if (msg_size < sizeof (struct CollectMessage))
1077 return GNUNET_SYSERR;
1079 if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
1082 return GNUNET_SYSERR;
1084 attr = (const char *) &c_msg[1];
1086 if ( ('\0' != attr[msg_size - sizeof (struct CollectMessage) - 1]) ||
1087 (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
1090 return GNUNET_SYSERR;
1096 client_disconnect_cb (void *cls,
1097 struct GNUNET_SERVICE_Client *client,
1100 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1101 "Client %p disconnected\n",
1106 client_connect_cb (void *cls,
1107 struct GNUNET_SERVICE_Client *client,
1108 struct GNUNET_MQ_Handle *mq)
1110 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1111 "Client %p connected\n",
1117 * Process Credential requests.
1119 * @param cls closure
1120 * @param c configuration to use
1121 * @param handle service handle
1125 const struct GNUNET_CONFIGURATION_Handle *c,
1126 struct GNUNET_SERVICE_Handle *handle)
1129 gns = GNUNET_GNS_connect (c);
1133 _("Failed to connect to GNS\n"));
1135 namestore = GNUNET_NAMESTORE_connect (c);
1136 if (NULL == namestore)
1139 _("Failed to connect to namestore\n"));
1142 statistics = GNUNET_STATISTICS_create ("credential", c);
1143 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1148 * Define "main" method using service macro
1152 GNUNET_SERVICE_OPTION_NONE,
1155 &client_disconnect_cb,
1157 GNUNET_MQ_hd_var_size (verify,
1158 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
1159 struct VerifyMessage,
1161 GNUNET_MQ_hd_var_size (collect,
1162 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT,
1163 struct CollectMessage,
1165 GNUNET_MQ_handler_end());
1167 /* end of gnunet-service-credential.c */