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 // For Looking up GNS request
35 #include <gnunet_dnsparser_lib.h>
36 #include <gnunet_identity_service.h>
37 #include <gnunet_gnsrecord_lib.h>
38 #include <gnunet_namestore_service.h>
39 #include <gnunet_gns_service.h>
40 #include "gnunet_gns_service.h"
45 #define GNUNET_CREDENTIAL_MAX_LENGTH 255
47 struct VerifyRequestHandle;
49 struct DelegationSetEntry;
52 struct DelegationChainEntry
57 struct DelegationChainEntry *next;
62 struct DelegationChainEntry *prev;
67 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
72 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
75 * The issued attribute
77 char *issuer_attribute;
80 * The delegated attribute
82 char *subject_attribute;
88 struct CredentialRecordEntry
93 struct CredentialRecordEntry *next;
98 struct CredentialRecordEntry *prev;
104 struct GNUNET_CREDENTIAL_CredentialRecordData *data;
113 * DLL used for delegations
114 * Used for OR delegations
116 struct DelegationQueueEntry
121 struct DelegationQueueEntry *next;
126 struct DelegationQueueEntry *prev;
129 * Sets under this Queue
131 struct DelegationSetEntry *set_entries_head;
134 * Sets under this Queue
136 struct DelegationSetEntry *set_entries_tail;
141 struct DelegationSetEntry *parent_set;
146 uint32_t required_solutions;
150 * DLL for delegation sets
151 * Used for AND delegation set
153 struct DelegationSetEntry
158 struct DelegationSetEntry *next;
163 struct DelegationSetEntry *prev;
168 struct GNUNET_GNS_LookupRequest *lookup_request;
173 struct VerifyRequestHandle *handle;
176 * Parent attribute delegation
178 struct DelegationQueueEntry *parent;
183 struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key;
186 * Queue entries of this set
188 struct DelegationQueueEntry *queue_entries_head;
191 * Queue entries of this set
193 struct DelegationQueueEntry *queue_entries_tail;
198 struct DelegationQueueEntry *parent_queue_entry;
201 * Issuer attribute delegated to
203 char *issuer_attribute;
206 * The current attribute to look up
208 char *lookup_attribute;
211 * Trailing attribute context
216 * Still to resolve delegation as string
218 char *unresolved_attribute_delegation;
221 * The delegation chain entry
223 struct DelegationChainEntry *delegation_chain_entry;
229 * Handle to a lookup operation from api
231 struct VerifyRequestHandle
235 * We keep these in a DLL.
237 struct VerifyRequestHandle *next;
240 * We keep these in a DLL.
242 struct VerifyRequestHandle *prev;
245 * Handle to the requesting client
247 struct GNUNET_SERVICE_Client *client;
252 struct GNUNET_GNS_LookupRequest *lookup_request;
255 * Size of delegation tree
257 uint32_t delegation_chain_size;
260 * Children of this attribute
262 struct DelegationChainEntry *delegation_chain_head;
265 * Children of this attribute
267 struct DelegationChainEntry *delegation_chain_tail;
272 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
277 char *issuer_attribute;
282 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
287 struct CredentialRecordEntry *cred_chain_head;
292 struct CredentialRecordEntry *cred_chain_tail;
295 * Root Delegation Set
297 struct DelegationSetEntry *root_set;
300 * Current Delegation Pointer
302 struct DelegationQueueEntry *current_delegation;
305 * The found credential
307 struct GNUNET_CREDENTIAL_CredentialRecordData *credential;
310 * Length of the credential
312 uint32_t credential_size;
322 uint64_t pending_lookups;
330 static struct VerifyRequestHandle *vrh_head;
335 static struct VerifyRequestHandle *vrh_tail;
338 * Handle to the statistics service
340 static struct GNUNET_STATISTICS_Handle *statistics;
343 * Handle to GNS service.
345 static struct GNUNET_GNS_Handle *gns;
349 cleanup_delegation_set (struct DelegationSetEntry *ds_entry)
351 struct DelegationQueueEntry *dq_entry;
352 struct DelegationSetEntry *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 if (NULL != ds_entry->issuer_key)
376 GNUNET_free (ds_entry->issuer_key);
377 if (NULL != ds_entry->lookup_attribute)
378 GNUNET_free (ds_entry->lookup_attribute);
379 if (NULL != ds_entry->issuer_attribute)
380 GNUNET_free (ds_entry->issuer_attribute);
381 if (NULL != ds_entry->unresolved_attribute_delegation)
382 GNUNET_free (ds_entry->unresolved_attribute_delegation);
383 if (NULL != ds_entry->attr_trailer)
384 GNUNET_free (ds_entry->attr_trailer);
385 if (NULL != ds_entry->lookup_request)
387 GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
388 ds_entry->lookup_request = NULL;
390 if (NULL != ds_entry->delegation_chain_entry)
392 if (NULL != ds_entry->delegation_chain_entry->subject_attribute)
393 GNUNET_free (ds_entry->delegation_chain_entry->subject_attribute);
394 if (NULL != ds_entry->delegation_chain_entry->issuer_attribute)
395 GNUNET_free (ds_entry->delegation_chain_entry->issuer_attribute);
396 GNUNET_free (ds_entry->delegation_chain_entry);
398 GNUNET_free (ds_entry);
402 cleanup_handle (struct VerifyRequestHandle *vrh)
404 struct CredentialRecordEntry *cr_entry;
405 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
407 if (NULL != vrh->lookup_request)
409 GNUNET_GNS_lookup_cancel (vrh->lookup_request);
410 vrh->lookup_request = NULL;
412 if (NULL != vrh->credential)
413 GNUNET_free (vrh->credential);
414 cleanup_delegation_set (vrh->root_set);
415 if (NULL != vrh->issuer_attribute)
416 GNUNET_free (vrh->issuer_attribute);
417 for (cr_entry = vrh->cred_chain_head;
418 NULL != vrh->cred_chain_head;
419 cr_entry = vrh->cred_chain_head)
421 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
422 vrh->cred_chain_tail,
424 if (NULL != cr_entry->data)
425 GNUNET_free (cr_entry->data);
426 GNUNET_free (cr_entry);
432 * Task run during shutdown.
438 shutdown_task (void *cls)
440 struct VerifyRequestHandle *vrh;
442 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
445 while (NULL != (vrh = vrh_head))
447 //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
448 GNUNET_CONTAINER_DLL_remove (vrh_head,
451 cleanup_handle (vrh);
456 GNUNET_GNS_disconnect (gns);
459 if (NULL != statistics)
461 GNUNET_STATISTICS_destroy (statistics,
469 * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY message
471 * @param cls client sending the message
472 * @param v_msg message of type `struct VerifyMessage`
473 * @return #GNUNET_OK if @a v_msg is well-formed
476 check_verify (void *cls,
477 const struct VerifyMessage *v_msg)
482 msg_size = ntohs (v_msg->header.size);
483 if (msg_size < sizeof (struct VerifyMessage))
486 return GNUNET_SYSERR;
488 if ((ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH) ||
489 (ntohs (v_msg->subject_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH))
492 return GNUNET_SYSERR;
494 attrs = (const char *) &v_msg[1];
496 if ( ('\0' != attrs[ntohs(v_msg->header.size) - sizeof (struct VerifyMessage) - 1]) ||
497 (strlen (attrs) > GNUNET_CREDENTIAL_MAX_LENGTH * 2) )
500 return GNUNET_SYSERR;
508 * @param handle the handle to the request
511 send_lookup_response (struct VerifyRequestHandle *vrh)
513 struct GNUNET_MQ_Envelope *env;
514 struct VerifyResultMessage *rmsg;
515 struct DelegationChainEntry *dce;
516 size_t size = vrh->credential_size;
517 struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
518 struct GNUNET_CREDENTIAL_Credential cred;
521 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
522 "Sending response\n");
524 for (dce = vrh->delegation_chain_head;
528 dd[i].issuer_key = dce->issuer_key;
529 dd[i].subject_key = dce->subject_key;
530 dd[i].issuer_attribute = dce->issuer_attribute;
531 dd[i].issuer_attribute_len = strlen (dce->issuer_attribute)+1;
532 dd[i].subject_attribute_len = 0;
533 if (NULL != dce->subject_attribute)
535 dd[i].subject_attribute = dce->subject_attribute;
536 dd[i].subject_attribute_len = strlen(dce->subject_attribute)+1;
542 * Get serialized record data
543 * Append at the end of rmsg
545 cred.issuer_key = vrh->credential->issuer_key;
546 cred.subject_key = vrh->credential->subject_key;
547 cred.issuer_attribute_len = strlen((char*)&vrh->credential[1])+1;
548 cred.issuer_attribute = (char*)&vrh->credential[1];
549 size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->delegation_chain_size,
552 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
553 "SIZE; %llu count: %d\n",size,vrh->delegation_chain_size);
554 env = GNUNET_MQ_msg_extra (rmsg,
556 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
557 //Assign id so that client can find associated request
558 rmsg->id = vrh->request_id;
559 rmsg->d_count = htonl (vrh->delegation_chain_size);
561 if (NULL != vrh->credential)
562 rmsg->cred_found = htonl (GNUNET_YES);
564 rmsg->cred_found = htonl (GNUNET_NO);
567 GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->delegation_chain_size,
573 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client),
575 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
578 GNUNET_STATISTICS_update (statistics,
579 "Completed verifications", 1,
585 backward_resolution (void* cls,
587 const struct GNUNET_GNSRECORD_Data *rd)
590 struct VerifyRequestHandle *vrh;
591 struct GNUNET_CREDENTIAL_CredentialRecordData *cred;
592 const struct GNUNET_CREDENTIAL_DelegationRecordData *sets;
593 struct CredentialRecordEntry *cred_pointer;
594 struct DelegationSetEntry *current_set;
595 struct DelegationSetEntry *ds_entry;
596 struct DelegationSetEntry *tmp_set;
597 struct DelegationQueueEntry *dq_entry;
599 char *lookup_attribute;
605 current_set->lookup_request = NULL;
606 vrh = current_set->handle;
607 vrh->pending_lookups--;
608 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
609 "Got %d attrs\n", rd_count);
612 for (i=0; i < rd_count; i++)
614 if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
618 struct GNUNET_CREDENTIAL_DelegationSetRecord set[ntohl(sets->set_count)];
619 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
620 "Found new attribute delegation with %d sets. Creating new Job...\n",
621 ntohl (sets->set_count));
623 if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size),
624 (const char*)&sets[1],
625 ntohl(sets->set_count),
628 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
629 "Failed to deserialize!\n");
632 dq_entry = GNUNET_new (struct DelegationQueueEntry);
633 dq_entry->required_solutions = ntohl(sets->set_count);
634 dq_entry->parent_set = current_set;
635 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
636 current_set->queue_entries_tail,
639 for (j=0; j<ntohl(sets->set_count); j++)
641 ds_entry = GNUNET_new (struct DelegationSetEntry);
642 if (NULL != current_set->attr_trailer)
644 if (0 == set[j].subject_attribute_len)
646 GNUNET_asprintf (&expanded_attr,
648 current_set->attr_trailer);
651 GNUNET_asprintf (&expanded_attr,
653 set[j].subject_attribute,
654 current_set->attr_trailer);
656 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
657 "Expanded to %s\n", expanded_attr);
658 ds_entry->unresolved_attribute_delegation = expanded_attr;
660 if (0 != set[j].subject_attribute_len)
662 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
663 "Not Expanding %s\n", set[j].subject_attribute);
664 ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute);
668 //Add a credential chain entry
669 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
670 ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
671 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
672 GNUNET_memcpy (ds_entry->issuer_key,
674 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
675 if (0 < set[j].subject_attribute_len)
676 ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute);
677 ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
678 ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute);
680 ds_entry->parent_queue_entry = dq_entry; //current_delegation;
681 GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head,
682 dq_entry->set_entries_tail,
685 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
686 "Checking for cred match\n");
688 * Check if this delegation already matches one of our credentials
690 for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL;
691 cred_pointer = cred_pointer->next)
693 cred = cred_pointer->data;
694 if(0 != memcmp (&set->subject_key,
695 &cred_pointer->data->issuer_key,
696 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
698 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
699 "Checking if %s matches %s\n",
700 ds_entry->unresolved_attribute_delegation, (char*)&cred[1]);
702 if (0 != strcmp (ds_entry->unresolved_attribute_delegation, (char*)&cred[1]))
705 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
709 for (tmp_set = ds_entry;
710 NULL != tmp_set->parent_queue_entry;
711 tmp_set = tmp_set->parent_queue_entry->parent_set)
713 tmp_set->parent_queue_entry->required_solutions--;
714 if (NULL != tmp_set->delegation_chain_entry)
716 vrh->delegation_chain_size++;
717 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
718 vrh->delegation_chain_tail,
719 tmp_set->delegation_chain_entry);
721 if (0 < tmp_set->parent_queue_entry->required_solutions)
725 if (NULL == tmp_set->parent_queue_entry)
727 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
728 "All solutions found\n");
729 vrh->credential = GNUNET_malloc (cred_pointer->data_size);
730 memcpy (vrh->credential,
732 cred_pointer->data_size);
733 vrh->credential_size = cred_pointer->data_size;
735 send_lookup_response (vrh);
740 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
741 "Building new lookup request from %s\n",
742 ds_entry->unresolved_attribute_delegation);
743 //Continue with backward resolution
744 char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1];
745 strcpy (issuer_attribute_name,
746 ds_entry->unresolved_attribute_delegation);
747 char *next_attr = strtok (issuer_attribute_name, ".");
748 GNUNET_asprintf (&lookup_attribute,
751 GNUNET_asprintf (&ds_entry->lookup_attribute,
754 if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation))
756 ds_entry->attr_trailer = NULL;
758 next_attr += strlen (next_attr) + 1;
759 ds_entry->attr_trailer = GNUNET_strdup (next_attr);
762 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
763 "Looking up %s\n", ds_entry->lookup_attribute);
764 if (NULL != ds_entry->attr_trailer)
765 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
766 "%s still to go...\n", ds_entry->attr_trailer);
768 vrh->pending_lookups++;
769 ds_entry->handle = vrh;
770 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
772 ds_entry->issuer_key, //issuer_key,
773 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
774 GNUNET_GNS_LO_DEFAULT,
775 NULL, //shorten_key, always NULL
776 &backward_resolution,
778 GNUNET_free (lookup_attribute);
782 if(0 == vrh->pending_lookups)
784 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
785 "We are all out of attributes...\n");
786 send_lookup_response (vrh);
794 * Result from GNS lookup.
796 * @param cls the closure (our client lookup handle)
797 * @param rd_count the number of records in @a rd
798 * @param rd the record data
801 handle_credential_query (void* cls,
803 const struct GNUNET_GNSRECORD_Data *rd)
805 struct VerifyRequestHandle *vrh = cls;
806 struct DelegationSetEntry *ds_entry;
807 const struct GNUNET_CREDENTIAL_CredentialRecordData *crd;
808 struct CredentialRecordEntry *cr_entry;
809 int cred_record_count;
812 vrh->lookup_request = NULL;
813 cred_record_count = 0;
814 for (i=0; i < rd_count; i++)
816 if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
820 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
825 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
826 "Invalid credential found\n");
829 cr_entry = GNUNET_new (struct CredentialRecordEntry);
830 cr_entry->data = GNUNET_malloc (rd[i].data_size);
831 memcpy (cr_entry->data,
834 cr_entry->data_size = rd[i].data_size;
835 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
836 vrh->cred_chain_tail,
839 if (0 != memcmp (&crd->issuer_key,
841 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
843 if (0 != strcmp ((char*)&crd[1], vrh->issuer_attribute))
845 vrh->credential = GNUNET_malloc (rd[i].data_size);
846 memcpy (vrh->credential,
849 vrh->credential_size = rd[i].data_size;
850 //Found match prematurely
851 send_lookup_response (vrh);
857 * Check for attributes from the issuer and follow the chain
858 * till you get the required subject's attributes
860 char issuer_attribute_name[strlen (vrh->issuer_attribute)];
861 strcpy (issuer_attribute_name,
862 vrh->issuer_attribute);
863 strcpy (issuer_attribute_name + strlen (vrh->issuer_attribute),
865 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
866 "Looking up %s\n", issuer_attribute_name);
867 ds_entry = GNUNET_new (struct DelegationSetEntry);
868 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
869 memcpy (ds_entry->issuer_key,
871 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
872 ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
873 ds_entry->handle = vrh;
874 ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
875 vrh->root_set = ds_entry;
876 vrh->pending_lookups = 1;
877 //Start with backward resolution
878 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
879 issuer_attribute_name,
880 &vrh->issuer_key, //issuer_key,
881 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
882 GNUNET_GNS_LO_DEFAULT,
883 NULL, //shorten_key, always NULL
884 &backward_resolution,
890 * Handle Credential verification requests from client
892 * @param cls the closure
893 * @param client the client
894 * @param message the message
897 handle_verify (void *cls,
898 const struct VerifyMessage *v_msg)
900 char attrs[GNUNET_CREDENTIAL_MAX_LENGTH*2 + 1];
901 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
902 char subject_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1 + 4];
903 struct VerifyRequestHandle *vrh;
904 struct GNUNET_SERVICE_Client *client = cls;
905 char *attrptr = attrs;
908 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
909 "Received VERIFY message\n");
911 utf_in = (const char *) &v_msg[1];
912 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
914 GNUNET_memcpy (issuer_attribute, attrs, ntohs (v_msg->issuer_attribute_len));
915 issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
916 GNUNET_memcpy (subject_attribute, attrs+strlen(issuer_attribute), ntohs (v_msg->subject_attribute_len));
917 strcpy (subject_attribute+ntohs (v_msg->subject_attribute_len),
919 subject_attribute[ntohs (v_msg->subject_attribute_len)+4] = '\0';
920 vrh = GNUNET_new (struct VerifyRequestHandle);
921 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
922 vrh->client = client;
923 vrh->request_id = v_msg->id;
924 vrh->issuer_key = v_msg->issuer_key;
925 vrh->subject_key = v_msg->subject_key;
926 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
928 if (NULL == subject_attribute)
930 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
931 "No subject attribute provided!\n");
932 send_lookup_response (vrh);
935 if (NULL == issuer_attribute)
937 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
938 "No issuer attribute provided!\n");
939 send_lookup_response (vrh);
942 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
946 * First, get attribute from subject
948 vrh->lookup_request = GNUNET_GNS_lookup (gns,
950 &v_msg->subject_key, //subject_pkey,
951 GNUNET_GNSRECORD_TYPE_CREDENTIAL,
952 GNUNET_GNS_LO_DEFAULT,
953 NULL, //shorten_key, always NULL
954 &handle_credential_query,
960 * One of our clients disconnected, clean up after it.
963 * @param client the client that disconnected
966 client_disconnect_cb (void *cls,
967 struct GNUNET_SERVICE_Client *client,
970 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
971 "Client %p disconnected\n",
976 * Add a client to our list of active clients.
979 * @param client client to add
980 * @param mq message queue for @a client
981 * @return this client
984 client_connect_cb (void *cls,
985 struct GNUNET_SERVICE_Client *client,
986 struct GNUNET_MQ_Handle *mq)
988 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
989 "Client %p connected\n",
995 * Process Credential requests.
998 * @param server the initialized server
999 * @param c configuration to use
1003 const struct GNUNET_CONFIGURATION_Handle *c,
1004 struct GNUNET_SERVICE_Handle *handle)
1007 gns = GNUNET_GNS_connect (c);
1011 _("Failed to connect to GNS\n"));
1014 statistics = GNUNET_STATISTICS_create ("credential", c);
1015 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1020 * Define "main" method using service macro
1024 GNUNET_SERVICE_OPTION_NONE,
1027 &client_disconnect_cb,
1029 GNUNET_MQ_hd_var_size (verify,
1030 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
1031 struct VerifyMessage,
1033 GNUNET_MQ_handler_end());
1035 /* end of gnunet-service-credential.c */