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
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.
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.
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.
21 * @file gns/gnunet-service-credential.c
22 * @brief GNU Credential Service (main service)
23 * @author Adnan Husain
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"
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>
41 #define GNUNET_CREDENTIAL_MAX_LENGTH 255
43 struct VerifyRequestHandle;
45 struct DelegationSetQueueEntry;
48 struct DelegationChainEntry
53 struct DelegationChainEntry *next;
58 struct DelegationChainEntry *prev;
63 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
68 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
71 * The issued attribute
73 char *issuer_attribute;
76 * The delegated attribute
78 char *subject_attribute;
84 struct CredentialRecordEntry
89 struct CredentialRecordEntry *next;
94 struct CredentialRecordEntry *prev;
100 struct GNUNET_CREDENTIAL_Credential *credential;
104 * DLL used for delegations
105 * Used for OR delegations
107 struct DelegationQueueEntry
112 struct DelegationQueueEntry *next;
117 struct DelegationQueueEntry *prev;
120 * Sets under this Queue
122 struct DelegationSetQueueEntry *set_entries_head;
125 * Sets under this Queue
127 struct DelegationSetQueueEntry *set_entries_tail;
132 struct DelegationSetQueueEntry *parent_set;
137 uint32_t required_solutions;
141 * DLL for delegation sets
142 * Used for AND delegation set
144 struct DelegationSetQueueEntry
149 struct DelegationSetQueueEntry *next;
154 struct DelegationSetQueueEntry *prev;
159 struct GNUNET_GNS_LookupRequest *lookup_request;
164 struct VerifyRequestHandle *handle;
167 * Parent attribute delegation
169 struct DelegationQueueEntry *parent;
174 struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key;
177 * Queue entries of this set
179 struct DelegationQueueEntry *queue_entries_head;
182 * Queue entries of this set
184 struct DelegationQueueEntry *queue_entries_tail;
189 struct DelegationQueueEntry *parent_queue_entry;
192 * Issuer attribute delegated to
194 char *issuer_attribute;
197 * The current attribute to look up
199 char *lookup_attribute;
202 * Trailing attribute context
207 * Still to resolve delegation as string
209 char *unresolved_attribute_delegation;
212 * The delegation chain entry
214 struct DelegationChainEntry *delegation_chain_entry;
220 * Handle to a lookup operation from api
222 struct VerifyRequestHandle
226 * We keep these in a DLL.
228 struct VerifyRequestHandle *next;
231 * We keep these in a DLL.
233 struct VerifyRequestHandle *prev;
236 * Handle to the requesting client
238 struct GNUNET_SERVICE_Client *client;
243 struct GNUNET_GNS_LookupRequest *lookup_request;
246 * Size of delegation tree
248 uint32_t delegation_chain_size;
251 * Children of this attribute
253 struct DelegationChainEntry *delegation_chain_head;
256 * Children of this attribute
258 struct DelegationChainEntry *delegation_chain_tail;
263 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
268 char *issuer_attribute;
273 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
278 struct CredentialRecordEntry *cred_chain_head;
283 struct CredentialRecordEntry *cred_chain_tail;
286 * Credential DLL size
288 uint32_t cred_chain_size;
291 * Root Delegation Set
293 struct DelegationSetQueueEntry *root_set;
296 * Current Delegation Pointer
298 struct DelegationQueueEntry *current_delegation;
308 uint64_t pending_lookups;
311 * Credential iterator
313 struct GNUNET_NAMESTORE_ZoneIterator *cred_collection_iter;
318 struct GNUNET_SCHEDULER_Task *collect_next_task;
326 static struct VerifyRequestHandle *vrh_head;
331 static struct VerifyRequestHandle *vrh_tail;
334 * Handle to the statistics service
336 static struct GNUNET_STATISTICS_Handle *statistics;
339 * Handle to GNS service.
341 static struct GNUNET_GNS_Handle *gns;
345 * Handle to namestore service
347 static struct GNUNET_NAMESTORE_Handle *namestore;
350 cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry)
352 struct DelegationQueueEntry *dq_entry;
353 struct DelegationSetQueueEntry *child;
355 if (NULL == ds_entry)
358 for (dq_entry = ds_entry->queue_entries_head;
360 dq_entry = ds_entry->queue_entries_head)
362 GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
363 ds_entry->queue_entries_tail,
365 for (child = dq_entry->set_entries_head;
367 child = dq_entry->set_entries_head)
369 GNUNET_CONTAINER_DLL_remove (dq_entry->set_entries_head,
370 dq_entry->set_entries_tail,
372 cleanup_delegation_set (child);
374 GNUNET_free (dq_entry);
376 if (NULL != ds_entry->issuer_key)
377 GNUNET_free (ds_entry->issuer_key);
378 if (NULL != ds_entry->lookup_attribute)
379 GNUNET_free (ds_entry->lookup_attribute);
380 if (NULL != ds_entry->issuer_attribute)
381 GNUNET_free (ds_entry->issuer_attribute);
382 if (NULL != ds_entry->unresolved_attribute_delegation)
383 GNUNET_free (ds_entry->unresolved_attribute_delegation);
384 if (NULL != ds_entry->attr_trailer)
385 GNUNET_free (ds_entry->attr_trailer);
386 if (NULL != ds_entry->lookup_request)
388 GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
389 ds_entry->lookup_request = NULL;
391 if (NULL != ds_entry->delegation_chain_entry)
393 if (NULL != ds_entry->delegation_chain_entry->subject_attribute)
394 GNUNET_free (ds_entry->delegation_chain_entry->subject_attribute);
395 if (NULL != ds_entry->delegation_chain_entry->issuer_attribute)
396 GNUNET_free (ds_entry->delegation_chain_entry->issuer_attribute);
397 GNUNET_free (ds_entry->delegation_chain_entry);
399 GNUNET_free (ds_entry);
403 cleanup_handle (struct VerifyRequestHandle *vrh)
405 struct CredentialRecordEntry *cr_entry;
406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
408 if (NULL != vrh->lookup_request)
410 GNUNET_GNS_lookup_cancel (vrh->lookup_request);
411 vrh->lookup_request = NULL;
413 cleanup_delegation_set (vrh->root_set);
414 if (NULL != vrh->issuer_attribute)
415 GNUNET_free (vrh->issuer_attribute);
416 for (cr_entry = vrh->cred_chain_head;
417 NULL != vrh->cred_chain_head;
418 cr_entry = vrh->cred_chain_head)
420 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
421 vrh->cred_chain_tail,
423 if (NULL != cr_entry->credential);
424 GNUNET_free (cr_entry->credential);
425 GNUNET_free (cr_entry);
431 * Task run during shutdown.
437 shutdown_task (void *cls)
439 struct VerifyRequestHandle *vrh;
441 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
444 while (NULL != (vrh = vrh_head))
446 //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
447 GNUNET_CONTAINER_DLL_remove (vrh_head,
450 cleanup_handle (vrh);
455 GNUNET_GNS_disconnect (gns);
458 if (NULL != namestore)
460 GNUNET_NAMESTORE_disconnect (namestore);
463 if (NULL != statistics)
465 GNUNET_STATISTICS_destroy (statistics,
477 * @param handle the handle to the request
480 send_lookup_response (struct VerifyRequestHandle *vrh)
482 struct GNUNET_MQ_Envelope *env;
483 struct DelegationChainResultMessage *rmsg;
484 struct DelegationChainEntry *dce;
485 struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
486 struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
487 struct CredentialRecordEntry *cd;
491 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
492 "Sending response\n");
493 dce = vrh->delegation_chain_head;
494 for (i=0;i<vrh->delegation_chain_size;i++)
496 dd[i].issuer_key = dce->issuer_key;
497 dd[i].subject_key = dce->subject_key;
498 dd[i].issuer_attribute = dce->issuer_attribute;
499 dd[i].issuer_attribute_len = strlen (dce->issuer_attribute)+1;
500 dd[i].subject_attribute_len = 0;
501 dd[i].subject_attribute = NULL;
502 if (NULL != dce->subject_attribute)
504 dd[i].subject_attribute = dce->subject_attribute;
505 dd[i].subject_attribute_len = strlen(dce->subject_attribute)+1;
511 * Get serialized record data
512 * Append at the end of rmsg
514 cd = vrh->cred_chain_head;
515 for (i=0;i<vrh->cred_chain_size;i++)
517 cred[i].issuer_key = cd->credential->issuer_key;
518 cred[i].subject_key = cd->credential->subject_key;
519 cred[i].issuer_attribute_len = strlen(cd->credential->issuer_attribute)+1;
520 cred[i].issuer_attribute = cd->credential->issuer_attribute;
521 cred[i].expiration = cd->credential->expiration;
522 cred[i].signature = cd->credential->signature;
525 size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->delegation_chain_size,
527 vrh->cred_chain_size,
529 env = GNUNET_MQ_msg_extra (rmsg,
531 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
532 //Assign id so that client can find associated request
533 rmsg->id = vrh->request_id;
534 rmsg->d_count = htonl (vrh->delegation_chain_size);
535 rmsg->c_count = htonl (vrh->cred_chain_size);
537 if (0 < vrh->cred_chain_size)
538 rmsg->cred_found = htonl (GNUNET_YES);
540 rmsg->cred_found = htonl (GNUNET_NO);
543 GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->delegation_chain_size,
545 vrh->cred_chain_size,
550 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client),
552 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
555 GNUNET_STATISTICS_update (statistics,
556 "Completed verifications", 1,
562 backward_resolution (void* cls,
564 const struct GNUNET_GNSRECORD_Data *rd)
567 struct VerifyRequestHandle *vrh;
568 const struct GNUNET_CREDENTIAL_DelegationRecord *sets;
569 struct CredentialRecordEntry *cred_pointer;
570 struct DelegationSetQueueEntry *current_set;
571 struct DelegationSetQueueEntry *ds_entry;
572 struct DelegationSetQueueEntry *tmp_set;
573 struct DelegationQueueEntry *dq_entry;
575 char *lookup_attribute;
581 current_set->lookup_request = NULL;
582 vrh = current_set->handle;
583 vrh->pending_lookups--;
584 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
585 "Got %d attrs\n", rd_count);
588 for (i=0; i < rd_count; i++)
590 if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
594 struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)];
595 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
596 "Found new attribute delegation with %d sets. Creating new Job...\n",
597 ntohl (sets->set_count));
599 if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size),
600 (const char*)&sets[1],
601 ntohl(sets->set_count),
604 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
605 "Failed to deserialize!\n");
608 dq_entry = GNUNET_new (struct DelegationQueueEntry);
609 dq_entry->required_solutions = ntohl(sets->set_count);
610 dq_entry->parent_set = current_set;
611 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
612 current_set->queue_entries_tail,
615 for (j=0; j<ntohl(sets->set_count); j++)
617 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
618 if (NULL != current_set->attr_trailer)
620 if (0 == set[j].subject_attribute_len)
622 GNUNET_asprintf (&expanded_attr,
624 current_set->attr_trailer);
627 GNUNET_asprintf (&expanded_attr,
629 set[j].subject_attribute,
630 current_set->attr_trailer);
632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
633 "Expanded to %s\n", expanded_attr);
634 ds_entry->unresolved_attribute_delegation = expanded_attr;
636 if (0 != set[j].subject_attribute_len)
638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
639 "Not Expanding %s\n", set[j].subject_attribute);
640 ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute);
644 //Add a credential chain entry
645 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
646 ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
647 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
648 GNUNET_memcpy (ds_entry->issuer_key,
650 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
651 if (0 < set[j].subject_attribute_len)
652 ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute);
653 ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
654 ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute);
656 ds_entry->parent_queue_entry = dq_entry; //current_delegation;
657 GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head,
658 dq_entry->set_entries_tail,
661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
662 "Checking for cred match\n");
664 * Check if this delegation already matches one of our credentials
666 for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL;
667 cred_pointer = cred_pointer->next)
669 if(0 != memcmp (&set->subject_key,
670 &cred_pointer->credential->issuer_key,
671 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
673 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
674 "Checking if %s matches %s\n",
675 ds_entry->unresolved_attribute_delegation,
676 cred_pointer->credential->issuer_attribute);
678 if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
679 cred_pointer->credential->issuer_attribute))
682 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
686 for (tmp_set = ds_entry;
687 NULL != tmp_set->parent_queue_entry;
688 tmp_set = tmp_set->parent_queue_entry->parent_set)
690 tmp_set->parent_queue_entry->required_solutions--;
691 if (NULL != tmp_set->delegation_chain_entry)
693 vrh->delegation_chain_size++;
694 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
695 vrh->delegation_chain_tail,
696 tmp_set->delegation_chain_entry);
698 if (0 < tmp_set->parent_queue_entry->required_solutions)
702 if (NULL == tmp_set->parent_queue_entry)
704 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
705 "All solutions found\n");
707 send_lookup_response (vrh);
710 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
711 "Not all solutions found yet.\n");
715 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
716 "Building new lookup request from %s\n",
717 ds_entry->unresolved_attribute_delegation);
718 //Continue with backward resolution
719 char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1];
720 strcpy (issuer_attribute_name,
721 ds_entry->unresolved_attribute_delegation);
722 char *next_attr = strtok (issuer_attribute_name, ".");
723 GNUNET_asprintf (&lookup_attribute,
726 GNUNET_asprintf (&ds_entry->lookup_attribute,
729 if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation))
731 ds_entry->attr_trailer = NULL;
733 next_attr += strlen (next_attr) + 1;
734 ds_entry->attr_trailer = GNUNET_strdup (next_attr);
737 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
738 "Looking up %s\n", ds_entry->lookup_attribute);
739 if (NULL != ds_entry->attr_trailer)
740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
741 "%s still to go...\n", ds_entry->attr_trailer);
743 vrh->pending_lookups++;
744 ds_entry->handle = vrh;
745 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
747 ds_entry->issuer_key, //issuer_key,
748 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
749 GNUNET_GNS_LO_DEFAULT,
750 NULL, //shorten_key, always NULL
751 &backward_resolution,
753 GNUNET_free (lookup_attribute);
757 if(0 == vrh->pending_lookups)
759 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
760 "We are all out of attributes...\n");
761 send_lookup_response (vrh);
769 * Result from GNS lookup.
771 * @param cls the closure (our client lookup handle)
772 * @param rd_count the number of records in @a rd
773 * @param rd the record data
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 //Found match prematurely
800 send_lookup_response (vrh);
806 * Check for attributes from the issuer and follow the chain
807 * till you get the required subject's attributes
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),
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,
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 NULL, //shorten_key, always NULL
833 &backward_resolution,
838 * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY message
840 * @param cls client sending the message
841 * @param v_msg message of type `struct VerifyMessage`
842 * @return #GNUNET_OK if @a v_msg is well-formed
845 check_verify (void *cls,
846 const struct VerifyMessage *v_msg)
851 msg_size = ntohs (v_msg->header.size);
852 if (msg_size < sizeof (struct VerifyMessage))
855 return GNUNET_SYSERR;
857 if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
860 return GNUNET_SYSERR;
862 attr = (const char *) &v_msg[1];
864 if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH)
867 return GNUNET_SYSERR;
873 * Handle Credential verification requests from client
875 * @param cls the closure
876 * @param client the client
877 * @param message the message
880 handle_verify (void *cls,
881 const struct VerifyMessage *v_msg)
883 struct VerifyRequestHandle *vrh;
884 struct GNUNET_SERVICE_Client *client = cls;
885 struct CredentialRecordEntry *cr_entry;
886 uint32_t credentials_count;
887 uint32_t credential_data_size;
889 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
890 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
891 char *attrptr = attr;
892 char *credential_data;
895 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
896 "Received VERIFY message\n");
897 utf_in = (const char *) &v_msg[1];
898 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
899 GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
900 issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
901 vrh = GNUNET_new (struct VerifyRequestHandle);
902 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
903 vrh->client = client;
904 vrh->request_id = v_msg->id;
905 vrh->issuer_key = v_msg->issuer_key;
906 vrh->subject_key = v_msg->subject_key;
907 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
908 if (NULL == issuer_attribute)
910 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
911 "No issuer attribute provided!\n");
912 send_lookup_response (vrh);
916 * First, collect credentials
919 credentials_count = ntohl(v_msg->c_count);
920 credential_data_size = ntohs (v_msg->header.size)
921 - sizeof (struct VerifyMessage)
922 - ntohs (v_msg->issuer_attribute_len)
924 struct GNUNET_CREDENTIAL_Credential credentials[credentials_count];
925 credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
926 if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize (credential_data_size,
931 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
932 "Cannot deserialize credentials!\n");
933 send_lookup_response (vrh);
937 for (i=0;i<credentials_count;i++) {
938 cr_entry = GNUNET_new (struct CredentialRecordEntry);
939 cr_entry->credential = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) +
940 strlen (credentials[i].issuer_attribute) + 1);
941 GNUNET_memcpy (cr_entry->credential,
943 sizeof (struct GNUNET_CREDENTIAL_Credential));
944 GNUNET_memcpy (&cr_entry->credential[1],
945 credentials[i].issuer_attribute,
946 strlen (credentials[i].issuer_attribute));
947 cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1];
948 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
949 vrh->cred_chain_tail,
951 vrh->cred_chain_size++;
954 delegation_chain_resolution_start (vrh);
959 * We encountered an error while collecting
962 handle_cred_collection_error_cb (void *cls)
964 struct VerifyRequestHandle *vrh = cls;
965 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
966 "Got disconnected from namestore database.\n");
967 vrh->cred_collection_iter = NULL;
968 send_lookup_response (vrh);
972 collect_next (void *cls)
974 struct VerifyRequestHandle *vrh = cls;
975 vrh->collect_next_task = NULL;
976 GNUNET_assert (NULL != vrh->cred_collection_iter);
977 GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter);
984 handle_cred_collection_cb (void *cls,
985 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
987 unsigned int rd_count,
988 const struct GNUNET_GNSRECORD_Data *rd)
990 struct VerifyRequestHandle *vrh = cls;
991 struct GNUNET_CREDENTIAL_Credential *crd;
992 struct CredentialRecordEntry *cr_entry;
993 int cred_record_count;
996 cred_record_count = 0;
997 for (i=0; i < rd_count; i++)
999 if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
1001 cred_record_count++;
1002 crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
1006 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1007 "Invalid credential found\n");
1010 cr_entry = GNUNET_new (struct CredentialRecordEntry);
1011 cr_entry->credential = crd;
1012 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
1013 vrh->cred_chain_tail,
1015 vrh->cred_chain_size++;
1017 vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next,
1022 * We encountered an error while collecting
1025 handle_cred_collection_finished_cb (void *cls)
1027 struct VerifyRequestHandle *vrh = cls;
1028 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1029 "Done collecting credentials.\n");
1030 vrh->cred_collection_iter = NULL;
1031 delegation_chain_resolution_start (vrh);
1035 * Handle Credential collection requests from client
1037 * @param cls the closure
1038 * @param client the client
1039 * @param message the message
1042 handle_collect (void *cls,
1043 const struct CollectMessage *c_msg)
1045 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1046 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1047 struct VerifyRequestHandle *vrh;
1048 struct GNUNET_SERVICE_Client *client = cls;
1049 char *attrptr = attr;
1052 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1053 "Received COLLECT message\n");
1055 utf_in = (const char *) &c_msg[1];
1056 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
1058 GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
1059 issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
1060 vrh = GNUNET_new (struct VerifyRequestHandle);
1061 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
1062 vrh->client = client;
1063 vrh->request_id = c_msg->id;
1064 vrh->issuer_key = c_msg->issuer_key;
1065 GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key,
1067 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
1069 if (NULL == issuer_attribute)
1071 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1072 "No issuer attribute provided!\n");
1073 send_lookup_response (vrh);
1076 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1077 "Getting credentials for subject\n");
1079 * First, get attribute from subject
1081 vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore,
1082 &c_msg->subject_key,
1083 &handle_cred_collection_error_cb,
1085 &handle_cred_collection_cb,
1087 &handle_cred_collection_finished_cb,
1093 * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT message
1095 * @param cls client sending the message
1096 * @param v_msg message of type `struct CollectMessage`
1097 * @return #GNUNET_OK if @a v_msg is well-formed
1100 check_collect (void *cls,
1101 const struct CollectMessage *c_msg)
1106 msg_size = ntohs (c_msg->header.size);
1107 if (msg_size < sizeof (struct CollectMessage))
1110 return GNUNET_SYSERR;
1112 if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
1115 return GNUNET_SYSERR;
1117 attr = (const char *) &c_msg[1];
1119 if ( ('\0' != attr[ntohs(c_msg->header.size) - sizeof (struct CollectMessage) - 1]) ||
1120 (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
1123 return GNUNET_SYSERR;
1129 * One of our clients disconnected, clean up after it.
1132 * @param client the client that disconnected
1135 client_disconnect_cb (void *cls,
1136 struct GNUNET_SERVICE_Client *client,
1139 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1140 "Client %p disconnected\n",
1145 * Add a client to our list of active clients.
1148 * @param client client to add
1149 * @param mq message queue for @a client
1150 * @return this client
1153 client_connect_cb (void *cls,
1154 struct GNUNET_SERVICE_Client *client,
1155 struct GNUNET_MQ_Handle *mq)
1157 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1158 "Client %p connected\n",
1164 * Process Credential requests.
1166 * @param cls closure
1167 * @param server the initialized server
1168 * @param c configuration to use
1172 const struct GNUNET_CONFIGURATION_Handle *c,
1173 struct GNUNET_SERVICE_Handle *handle)
1176 gns = GNUNET_GNS_connect (c);
1180 _("Failed to connect to GNS\n"));
1182 namestore = GNUNET_NAMESTORE_connect (c);
1183 if (NULL == namestore)
1186 _("Failed to connect to namestore\n"));
1189 statistics = GNUNET_STATISTICS_create ("credential", c);
1190 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1195 * Define "main" method using service macro
1199 GNUNET_SERVICE_OPTION_NONE,
1202 &client_disconnect_cb,
1204 GNUNET_MQ_hd_var_size (verify,
1205 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
1206 struct VerifyMessage,
1208 GNUNET_MQ_hd_var_size (collect,
1209 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT,
1210 struct CollectMessage,
1212 GNUNET_MQ_handler_end());
1214 /* end of gnunet-service-credential.c */