aboutsummaryrefslogtreecommitdiff
path: root/src/credential/gnunet-service-credential.c
diff options
context:
space:
mode:
authorSchanzenbach, Martin <mschanzenbach@posteo.de>2016-12-28 18:40:17 +0100
committerSchanzenbach, Martin <mschanzenbach@posteo.de>2016-12-28 18:40:17 +0100
commita84624407eedd5418d36de590571da47d2f47015 (patch)
tree2f8d9fd84df5f1dba55a4e85c7d98722cc42cada /src/credential/gnunet-service-credential.c
parent43b34377e10d329075327104e4a295ee9d3c53b4 (diff)
downloadgnunet-a84624407eedd5418d36de590571da47d2f47015.tar.gz
gnunet-a84624407eedd5418d36de590571da47d2f47015.zip
-change api
Diffstat (limited to 'src/credential/gnunet-service-credential.c')
-rw-r--r--src/credential/gnunet-service-credential.c367
1 files changed, 276 insertions, 91 deletions
diff --git a/src/credential/gnunet-service-credential.c b/src/credential/gnunet-service-credential.c
index 942b38652..4841370b3 100644
--- a/src/credential/gnunet-service-credential.c
+++ b/src/credential/gnunet-service-credential.c
@@ -31,15 +31,11 @@
31#include "gnunet_protocols.h" 31#include "gnunet_protocols.h"
32#include "gnunet_signatures.h" 32#include "gnunet_signatures.h"
33 33
34// For Looking up GNS request
35#include <gnunet_dnsparser_lib.h> 34#include <gnunet_dnsparser_lib.h>
36#include <gnunet_identity_service.h> 35#include <gnunet_identity_service.h>
37#include <gnunet_gnsrecord_lib.h> 36#include <gnunet_gnsrecord_lib.h>
38#include <gnunet_namestore_service.h> 37#include <gnunet_namestore_service.h>
39#include <gnunet_gns_service.h> 38#include <gnunet_gns_service.h>
40#include "gnunet_gns_service.h"
41
42
43 39
44 40
45#define GNUNET_CREDENTIAL_MAX_LENGTH 255 41#define GNUNET_CREDENTIAL_MAX_LENGTH 255
@@ -311,6 +307,16 @@ struct VerifyRequestHandle
311 */ 307 */
312 uint64_t pending_lookups; 308 uint64_t pending_lookups;
313 309
310 /**
311 * Credential iterator
312 */
313 struct GNUNET_NAMESTORE_ZoneIterator *cred_collection_iter;
314
315 /**
316 * Collect task
317 */
318 struct GNUNET_SCHEDULER_Task *collect_next_task;
319
314}; 320};
315 321
316 322
@@ -335,6 +341,11 @@ static struct GNUNET_STATISTICS_Handle *statistics;
335static struct GNUNET_GNS_Handle *gns; 341static struct GNUNET_GNS_Handle *gns;
336 342
337 343
344/**
345 * Handle to namestore service
346 */
347static struct GNUNET_NAMESTORE_Handle *namestore;
348
338static void 349static void
339cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry) 350cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry)
340{ 351{
@@ -444,6 +455,11 @@ shutdown_task (void *cls)
444 GNUNET_GNS_disconnect (gns); 455 GNUNET_GNS_disconnect (gns);
445 gns = NULL; 456 gns = NULL;
446 } 457 }
458 if (NULL != namestore)
459 {
460 GNUNET_NAMESTORE_disconnect (namestore);
461 namestore = NULL;
462 }
447 if (NULL != statistics) 463 if (NULL != statistics)
448 { 464 {
449 GNUNET_STATISTICS_destroy (statistics, 465 GNUNET_STATISTICS_destroy (statistics,
@@ -453,42 +469,7 @@ shutdown_task (void *cls)
453 469
454} 470}
455 471
456/**
457 * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY message
458 *
459 * @param cls client sending the message
460 * @param v_msg message of type `struct VerifyMessage`
461 * @return #GNUNET_OK if @a v_msg is well-formed
462 */
463static int
464check_verify (void *cls,
465 const struct VerifyMessage *v_msg)
466{
467 size_t msg_size;
468 const char* attrs;
469 472
470 msg_size = ntohs (v_msg->header.size);
471 if (msg_size < sizeof (struct VerifyMessage))
472 {
473 GNUNET_break (0);
474 return GNUNET_SYSERR;
475 }
476 if ((ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH) ||
477 (ntohs (v_msg->subject_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH))
478 {
479 GNUNET_break (0);
480 return GNUNET_SYSERR;
481 }
482 attrs = (const char *) &v_msg[1];
483
484 if ( ('\0' != attrs[ntohs(v_msg->header.size) - sizeof (struct VerifyMessage) - 1]) ||
485 (strlen (attrs) > GNUNET_CREDENTIAL_MAX_LENGTH * 2) )
486 {
487 GNUNET_break (0);
488 return GNUNET_SYSERR;
489 }
490 return GNUNET_OK;
491}
492 473
493/** 474/**
494 * Send. 475 * Send.
@@ -499,7 +480,7 @@ static void
499send_lookup_response (struct VerifyRequestHandle *vrh) 480send_lookup_response (struct VerifyRequestHandle *vrh)
500{ 481{
501 struct GNUNET_MQ_Envelope *env; 482 struct GNUNET_MQ_Envelope *env;
502 struct VerifyResultMessage *rmsg; 483 struct DelegationChainResultMessage *rmsg;
503 struct DelegationChainEntry *dce; 484 struct DelegationChainEntry *dce;
504 struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size]; 485 struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
505 struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size]; 486 struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
@@ -792,21 +773,14 @@ backward_resolution (void* cls,
792 * @param rd the record data 773 * @param rd the record data
793 */ 774 */
794static void 775static void
795handle_credential_query (void* cls, 776delegation_chain_resolution_start (void* cls)
796 uint32_t rd_count,
797 const struct GNUNET_GNSRECORD_Data *rd)
798{ 777{
799 struct VerifyRequestHandle *vrh = cls; 778 struct VerifyRequestHandle *vrh = cls;
800 struct DelegationSetQueueEntry *ds_entry; 779 struct DelegationSetQueueEntry *ds_entry;
801 struct GNUNET_CREDENTIAL_Credential *crd;
802 struct CredentialRecordEntry *cr_entry; 780 struct CredentialRecordEntry *cr_entry;
803 int cred_record_count;
804 int i;
805
806 vrh->lookup_request = NULL; 781 vrh->lookup_request = NULL;
807 cred_record_count = 0;
808 782
809 if (0 == rd_count) 783 if (0 == vrh->cred_chain_size)
810 { 784 {
811 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 785 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
812 "No credentials found\n"); 786 "No credentials found\n");
@@ -814,31 +788,13 @@ handle_credential_query (void* cls,
814 return; 788 return;
815 } 789 }
816 790
817 for (i=0; i < rd_count; i++) 791 for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = cr_entry->next)
818 { 792 {
819 if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type) 793 if (0 != memcmp (&cr_entry->credential->issuer_key,
820 continue;
821 cred_record_count++;
822 crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
823 rd[i].data_size);
824 if (NULL == crd)
825 {
826 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
827 "Invalid credential found\n");
828 continue;
829 }
830 cr_entry = GNUNET_new (struct CredentialRecordEntry);
831 cr_entry->credential = crd;
832 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
833 vrh->cred_chain_tail,
834 cr_entry);
835 vrh->cred_chain_size++;
836
837 if (0 != memcmp (&crd->issuer_key,
838 &vrh->issuer_key, 794 &vrh->issuer_key,
839 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) 795 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
840 continue; 796 continue;
841 if (0 != strcmp (crd->issuer_attribute, vrh->issuer_attribute)) 797 if (0 != strcmp (cr_entry->credential->issuer_attribute, vrh->issuer_attribute))
842 continue; 798 continue;
843 //Found match prematurely 799 //Found match prematurely
844 send_lookup_response (vrh); 800 send_lookup_response (vrh);
@@ -878,6 +834,40 @@ handle_credential_query (void* cls,
878 ds_entry); 834 ds_entry);
879} 835}
880 836
837/**
838 * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY message
839 *
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
843 */
844static int
845check_verify (void *cls,
846 const struct VerifyMessage *v_msg)
847{
848 size_t msg_size;
849 const char* attr;
850
851 msg_size = ntohs (v_msg->header.size);
852 if (msg_size < sizeof (struct VerifyMessage))
853 {
854 GNUNET_break (0);
855 return GNUNET_SYSERR;
856 }
857 if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
858 {
859 GNUNET_break (0);
860 return GNUNET_SYSERR;
861 }
862 attr = (const char *) &v_msg[1];
863
864 if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH)
865 {
866 GNUNET_break (0);
867 return GNUNET_SYSERR;
868 }
869 return GNUNET_OK;
870}
881 871
882/** 872/**
883 * Handle Credential verification requests from client 873 * Handle Credential verification requests from client
@@ -890,12 +880,11 @@ static void
890handle_verify (void *cls, 880handle_verify (void *cls,
891 const struct VerifyMessage *v_msg) 881 const struct VerifyMessage *v_msg)
892{ 882{
893 char attrs[GNUNET_CREDENTIAL_MAX_LENGTH*2 + 1]; 883 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
894 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1]; 884 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
895 char subject_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1 + 4];
896 struct VerifyRequestHandle *vrh; 885 struct VerifyRequestHandle *vrh;
897 struct GNUNET_SERVICE_Client *client = cls; 886 struct GNUNET_SERVICE_Client *client = cls;
898 char *attrptr = attrs; 887 char *attrptr = attr;
899 const char *utf_in; 888 const char *utf_in;
900 889
901 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 890 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -904,12 +893,8 @@ handle_verify (void *cls,
904 utf_in = (const char *) &v_msg[1]; 893 utf_in = (const char *) &v_msg[1];
905 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr); 894 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
906 895
907 GNUNET_memcpy (issuer_attribute, attrs, ntohs (v_msg->issuer_attribute_len)); 896 GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
908 issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0'; 897 issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
909 GNUNET_memcpy (subject_attribute, attrs+strlen(issuer_attribute), ntohs (v_msg->subject_attribute_len));
910 strcpy (subject_attribute+ntohs (v_msg->subject_attribute_len),
911 ".gnu");
912 subject_attribute[ntohs (v_msg->subject_attribute_len)+4] = '\0';
913 vrh = GNUNET_new (struct VerifyRequestHandle); 898 vrh = GNUNET_new (struct VerifyRequestHandle);
914 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh); 899 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
915 vrh->client = client; 900 vrh->client = client;
@@ -917,14 +902,169 @@ handle_verify (void *cls,
917 vrh->issuer_key = v_msg->issuer_key; 902 vrh->issuer_key = v_msg->issuer_key;
918 vrh->subject_key = v_msg->subject_key; 903 vrh->subject_key = v_msg->subject_key;
919 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute); 904 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
920 905 if (NULL == issuer_attribute)
921 if (NULL == subject_attribute)
922 { 906 {
923 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 907 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
924 "No subject attribute provided!\n"); 908 "No issuer attribute provided!\n");
909 send_lookup_response (vrh);
910 return;
911 }
912 /**
913 * First, collect credentials
914 * TODO: cleanup!
915 */
916 uint32_t credentials_count = ntohl(v_msg->c_count);
917 int i;
918 uint32_t credential_data_size = ntohs (v_msg->header.size)
919 - sizeof (struct VerifyMessage)
920 - ntohs (v_msg->issuer_attribute_len)
921 - 1;
922 struct GNUNET_CREDENTIAL_Credential credentials[credentials_count];
923 char *credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
924 struct CredentialRecordEntry *cr_entry;
925 if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize (credential_data_size,
926 credential_data,
927 credentials_count,
928 credentials))
929 {
930 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
931 "Cannot deserialize credentials!\n");
925 send_lookup_response (vrh); 932 send_lookup_response (vrh);
926 return; 933 return;
927 } 934 }
935
936 for (i=0;i<credentials_count;i++) {
937 cr_entry = GNUNET_new (struct CredentialRecordEntry);
938 cr_entry->credential = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) +
939 strlen (credentials[i].issuer_attribute) + 1);
940 GNUNET_memcpy (cr_entry->credential,
941 &credentials[i],
942 sizeof (struct GNUNET_CREDENTIAL_Credential));
943 GNUNET_memcpy (&cr_entry->credential[1],
944 credentials[i].issuer_attribute,
945 strlen (credentials[i].issuer_attribute));
946 cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1];
947 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
948 vrh->cred_chain_tail,
949 cr_entry);
950 vrh->cred_chain_size++;
951 }
952
953 delegation_chain_resolution_start (vrh);
954
955}
956
957/**
958 * We encountered an error while collecting
959 */
960static void
961handle_cred_collection_error_cb (void *cls)
962{
963 struct VerifyRequestHandle *vrh = cls;
964 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
965 "Got disconnected from namestore database.\n");
966 vrh->cred_collection_iter = NULL;
967 send_lookup_response (vrh);
968}
969
970static void
971collect_next (void *cls)
972{
973 struct VerifyRequestHandle *vrh = cls;
974 vrh->collect_next_task = NULL;
975 GNUNET_assert (NULL != vrh->cred_collection_iter);
976 GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter);
977}
978
979/**
980 * Store credential
981 */
982static void
983handle_cred_collection_cb (void *cls,
984 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
985 const char *label,
986 unsigned int rd_count,
987 const struct GNUNET_GNSRECORD_Data *rd)
988{
989 struct VerifyRequestHandle *vrh = cls;
990 struct GNUNET_CREDENTIAL_Credential *crd;
991 struct CredentialRecordEntry *cr_entry;
992 int cred_record_count;
993 int i;
994
995 cred_record_count = 0;
996 for (i=0; i < rd_count; i++)
997 {
998 if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
999 continue;
1000 cred_record_count++;
1001 crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
1002 rd[i].data_size);
1003 if (NULL == crd)
1004 {
1005 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1006 "Invalid credential found\n");
1007 continue;
1008 }
1009 cr_entry = GNUNET_new (struct CredentialRecordEntry);
1010 cr_entry->credential = crd;
1011 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
1012 vrh->cred_chain_tail,
1013 cr_entry);
1014 vrh->cred_chain_size++;
1015 }
1016 vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next,
1017 vrh);
1018}
1019
1020/**
1021 * We encountered an error while collecting
1022 */
1023static void
1024handle_cred_collection_finished_cb (void *cls)
1025{
1026 struct VerifyRequestHandle *vrh = cls;
1027 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1028 "Done collecting credentials.\n");
1029 vrh->cred_collection_iter = NULL;
1030 delegation_chain_resolution_start (vrh);
1031}
1032
1033/**
1034 * Handle Credential collection requests from client
1035 *
1036 * @param cls the closure
1037 * @param client the client
1038 * @param message the message
1039 */
1040static void
1041handle_collect (void *cls,
1042 const struct CollectMessage *c_msg)
1043{
1044 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1045 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1046 struct VerifyRequestHandle *vrh;
1047 struct GNUNET_SERVICE_Client *client = cls;
1048 char *attrptr = attr;
1049 const char *utf_in;
1050
1051 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1052 "Received COLLECT message\n");
1053
1054 utf_in = (const char *) &c_msg[1];
1055 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
1056
1057 GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
1058 issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
1059 vrh = GNUNET_new (struct VerifyRequestHandle);
1060 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
1061 vrh->client = client;
1062 vrh->request_id = c_msg->id;
1063 vrh->issuer_key = c_msg->issuer_key;
1064 GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key,
1065 &vrh->subject_key);
1066 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
1067
928 if (NULL == issuer_attribute) 1068 if (NULL == issuer_attribute)
929 { 1069 {
930 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1070 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -933,23 +1073,58 @@ handle_verify (void *cls,
933 return; 1073 return;
934 } 1074 }
935 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1075 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
936 "Looking up %s\n", 1076 "Getting credentials for subject\n");
937 subject_attribute);
938 /** 1077 /**
939 * First, get attribute from subject 1078 * First, get attribute from subject
940 */ 1079 */
941 vrh->lookup_request = GNUNET_GNS_lookup (gns, 1080 vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore,
942 subject_attribute, 1081 &c_msg->subject_key,
943 &v_msg->subject_key, //subject_pkey, 1082 &handle_cred_collection_error_cb,
944 GNUNET_GNSRECORD_TYPE_CREDENTIAL, 1083 vrh,
945 GNUNET_GNS_LO_DEFAULT, 1084 &handle_cred_collection_cb,
946 NULL, //shorten_key, always NULL 1085 vrh,
947 &handle_credential_query, 1086 &handle_cred_collection_finished_cb,
948 vrh); 1087 vrh);
949} 1088}
950 1089
951 1090
952/** 1091/**
1092 * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT message
1093 *
1094 * @param cls client sending the message
1095 * @param v_msg message of type `struct CollectMessage`
1096 * @return #GNUNET_OK if @a v_msg is well-formed
1097 */
1098static int
1099check_collect (void *cls,
1100 const struct CollectMessage *c_msg)
1101{
1102 size_t msg_size;
1103 const char* attr;
1104
1105 msg_size = ntohs (c_msg->header.size);
1106 if (msg_size < sizeof (struct CollectMessage))
1107 {
1108 GNUNET_break (0);
1109 return GNUNET_SYSERR;
1110 }
1111 if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
1112 {
1113 GNUNET_break (0);
1114 return GNUNET_SYSERR;
1115 }
1116 attr = (const char *) &c_msg[1];
1117
1118 if ( ('\0' != attr[ntohs(c_msg->header.size) - sizeof (struct CollectMessage) - 1]) ||
1119 (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
1120 {
1121 GNUNET_break (0);
1122 return GNUNET_SYSERR;
1123 }
1124 return GNUNET_OK;
1125}
1126
1127/**
953 * One of our clients disconnected, clean up after it. 1128 * One of our clients disconnected, clean up after it.
954 * 1129 *
955 * @param cls NULL 1130 * @param cls NULL
@@ -1003,6 +1178,12 @@ run (void *cls,
1003 fprintf (stderr, 1178 fprintf (stderr,
1004 _("Failed to connect to GNS\n")); 1179 _("Failed to connect to GNS\n"));
1005 } 1180 }
1181 namestore = GNUNET_NAMESTORE_connect (c);
1182 if (NULL == namestore)
1183 {
1184 fprintf (stderr,
1185 _("Failed to connect to namestore\n"));
1186 }
1006 1187
1007 statistics = GNUNET_STATISTICS_create ("credential", c); 1188 statistics = GNUNET_STATISTICS_create ("credential", c);
1008 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); 1189 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
@@ -1023,6 +1204,10 @@ GNUNET_SERVICE_MAIN
1023 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY, 1204 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
1024 struct VerifyMessage, 1205 struct VerifyMessage,
1025 NULL), 1206 NULL),
1207 GNUNET_MQ_hd_var_size (collect,
1208 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT,
1209 struct CollectMessage,
1210 NULL),
1026 GNUNET_MQ_handler_end()); 1211 GNUNET_MQ_handler_end());
1027 1212
1028/* end of gnunet-service-credential.c */ 1213/* end of gnunet-service-credential.c */