From a84624407eedd5418d36de590571da47d2f47015 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Wed, 28 Dec 2016 18:40:17 +0100 Subject: [PATCH] -change api --- src/credential/Makefile.am | 1 + src/credential/credential.h | 47 ++- src/credential/credential_api.c | 142 ++++++-- src/credential/credential_misc.c | 1 + src/credential/credential_serialization.c | 175 +++++++--- src/credential/credential_serialization.h | 17 + src/credential/gnunet-credential.c | 171 +++++++++- src/credential/gnunet-service-credential.c | 367 ++++++++++++++++----- src/credential/plugin_rest_credential.c | 3 +- src/credential/test_credential_collect.sh | 47 +++ src/credential/test_credential_lookup.conf | 2 +- src/credential/test_credential_verify.sh | 5 +- src/include/gnunet_credential_service.h | 15 +- src/include/gnunet_protocols.h | 4 + 14 files changed, 797 insertions(+), 200 deletions(-) create mode 100755 src/credential/test_credential_collect.sh diff --git a/src/credential/Makefile.am b/src/credential/Makefile.am index db3bc8027..ca11c5e4f 100644 --- a/src/credential/Makefile.am +++ b/src/credential/Makefile.am @@ -69,6 +69,7 @@ gnunet_service_credential_LDADD = \ libgnunetcredential.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(GN_LIBINTL) diff --git a/src/credential/credential.h b/src/credential/credential.h index c5c0183cc..f16249c1b 100644 --- a/src/credential/credential.h +++ b/src/credential/credential.h @@ -29,6 +29,41 @@ GNUNET_NETWORK_STRUCT_BEGIN +/** + * Message from client to Credential service to collect credentials. + */ +struct CollectMessage +{ + /** + * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY + */ + struct GNUNET_MessageHeader header; + + /** + * Subject public key + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey subject_key; + + /** + * Trust anchor + */ + struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key; + + /** + * Length of the issuer attribute + */ + uint16_t issuer_attribute_len; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; + + /* Followed by the zero-terminated attribute */ + +}; + + /** * Message from client to Credential service to verify attributes. */ @@ -50,21 +85,21 @@ struct VerifyMessage struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key; /** - * Length of the issuer attribute + * Number of credentials */ - uint16_t issuer_attribute_len; + uint32_t c_count; /** - * Length of the subject attribute + * Length of the issuer attribute */ - uint16_t subject_attribute_len; + uint16_t issuer_attribute_len; /** * Unique identifier for this request (for key collisions). */ uint32_t id GNUNET_PACKED; - /* Followed by the zero-terminated attributes to look up */ + /* Followed by the zero-terminated attribute and credentials to look up */ }; @@ -72,7 +107,7 @@ struct VerifyMessage /** * Message from CREDENTIAL service to client: new results. */ -struct VerifyResultMessage +struct DelegationChainResultMessage { /** * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT diff --git a/src/credential/credential_api.c b/src/credential/credential_api.c index e991b4153..b201d4d9c 100644 --- a/src/credential/credential_api.c +++ b/src/credential/credential_api.c @@ -61,7 +61,7 @@ struct GNUNET_CREDENTIAL_Request /** * processor to call on verify result */ - GNUNET_CREDENTIAL_VerifyResultProcessor verify_proc; + GNUNET_CREDENTIAL_CredentialResultProcessor verify_proc; /** * @e verify_proc closure @@ -100,12 +100,12 @@ struct GNUNET_CREDENTIAL_Handle /** * Head of linked list of active verify requests. */ - struct GNUNET_CREDENTIAL_Request *verify_head; + struct GNUNET_CREDENTIAL_Request *request_head; /** * Tail of linked list of active verify requests. */ - struct GNUNET_CREDENTIAL_Request *verify_tail; + struct GNUNET_CREDENTIAL_Request *request_tail; /** * Reconnect task @@ -185,7 +185,6 @@ mq_error_handler (void *cls, force_reconnect (handle); } - /** * Check validity of message received from the CREDENTIAL service * @@ -194,7 +193,7 @@ mq_error_handler (void *cls, */ static int check_result (void *cls, - const struct VerifyResultMessage *vr_msg) + const struct DelegationChainResultMessage *vr_msg) { //TODO return GNUNET_OK; @@ -209,7 +208,7 @@ check_result (void *cls, */ static void handle_result (void *cls, - const struct VerifyResultMessage *vr_msg) + const struct DelegationChainResultMessage *vr_msg) { struct GNUNET_CREDENTIAL_Handle *handle = cls; uint32_t r_id = ntohl (vr_msg->id); @@ -219,30 +218,30 @@ handle_result (void *cls, uint32_t c_count = ntohl (vr_msg->c_count); struct GNUNET_CREDENTIAL_Delegation d_chain[d_count]; struct GNUNET_CREDENTIAL_Credential creds[c_count]; - GNUNET_CREDENTIAL_VerifyResultProcessor proc; + GNUNET_CREDENTIAL_CredentialResultProcessor proc; void *proc_cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received verify reply from CREDENTIAL service\n"); - for (vr = handle->verify_head; NULL != vr; vr = vr->next) + for (vr = handle->request_head; NULL != vr; vr = vr->next) if (vr->r_id == r_id) break; if (NULL == vr) return; proc = vr->verify_proc; proc_cls = vr->proc_cls; - GNUNET_CONTAINER_DLL_remove (handle->verify_head, - handle->verify_tail, + GNUNET_CONTAINER_DLL_remove (handle->request_head, + handle->request_tail, vr); GNUNET_MQ_discard (vr->env); GNUNET_free (vr); GNUNET_assert (GNUNET_OK == GNUNET_CREDENTIAL_delegation_chain_deserialize (mlen, - (const char*) &vr_msg[1], - d_count, - d_chain, - c_count, - creds)); + (const char*) &vr_msg[1], + d_count, + d_chain, + c_count, + creds)); if (GNUNET_NO == ntohl (vr_msg->cred_found)) { proc (proc_cls, @@ -271,7 +270,11 @@ reconnect (struct GNUNET_CREDENTIAL_Handle *handle) struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size (result, GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT, - struct VerifyResultMessage, + struct DelegationChainResultMessage, + handle), + GNUNET_MQ_hd_var_size (result, + GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT, + struct DelegationChainResultMessage, handle), GNUNET_MQ_handler_end () }; @@ -287,7 +290,7 @@ reconnect (struct GNUNET_CREDENTIAL_Handle *handle) handle); if (NULL == handle->mq) return; - for (vr = handle->verify_head; NULL != vr; vr = vr->next) + for (vr = handle->request_head; NULL != vr; vr = vr->next) GNUNET_MQ_send_copy (handle->mq, vr->env); } @@ -334,7 +337,7 @@ GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle) GNUNET_SCHEDULER_cancel (handle->reconnect_task); handle->reconnect_task = NULL; } - GNUNET_assert (NULL == handle->verify_head); + GNUNET_assert (NULL == handle->request_head); GNUNET_free (handle); } @@ -349,13 +352,81 @@ GNUNET_CREDENTIAL_verify_cancel (struct GNUNET_CREDENTIAL_Request *vr) { struct GNUNET_CREDENTIAL_Handle *handle = vr->credential_handle; - GNUNET_CONTAINER_DLL_remove (handle->verify_head, - handle->verify_tail, + GNUNET_CONTAINER_DLL_remove (handle->request_head, + handle->request_tail, vr); GNUNET_MQ_discard (vr->env); GNUNET_free (vr); } + +/** + * Performs attribute collection. + * Collects all credentials of subject to fulfill the + * attribute, if possible + * + * @param handle handle to the Credential service + * @param issuer_key the issuer public key + * @param issuer_attribute the issuer attribute + * @param subject_key the subject public key + * @param credential_count number of credentials provided + * @param credentials subject credentials + * @param proc function to call on result + * @param proc_cls closure for processor + * @return handle to the queued request + */ +struct GNUNET_CREDENTIAL_Request* +GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle, + const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key, + const char *issuer_attribute, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key, + GNUNET_CREDENTIAL_CredentialResultProcessor proc, + void *proc_cls) +{ + /* IPC to shorten credential names, return shorten_handle */ + struct CollectMessage *c_msg; + struct GNUNET_CREDENTIAL_Request *vr; + size_t nlen; + + if (NULL == issuer_attribute) + { + GNUNET_break (0); + return NULL; + } + + //DEBUG LOG + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Trying to collect `%s' in CREDENTIAL\n", + issuer_attribute); + nlen = strlen (issuer_attribute) + 1; + if (nlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*vr)) + { + GNUNET_break (0); + return NULL; + } + vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request); + vr->credential_handle = handle; + vr->verify_proc = proc; + vr->proc_cls = proc_cls; + vr->r_id = handle->r_id_gen++; + vr->env = GNUNET_MQ_msg_extra (c_msg, + nlen, + GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT); + c_msg->id = htonl (vr->r_id); + c_msg->subject_key = *subject_key; + c_msg->issuer_key = *issuer_key; + c_msg->issuer_attribute_len = htons(strlen(issuer_attribute)); + GNUNET_memcpy (&c_msg[1], + issuer_attribute, + strlen (issuer_attribute)); + GNUNET_CONTAINER_DLL_insert (handle->request_head, + handle->request_tail, + vr); + if (NULL != handle->mq) + GNUNET_MQ_send_copy (handle->mq, + vr->env); + return vr; +} /** * Performs attribute verification. * Checks if there is a delegation chain from @@ -368,7 +439,8 @@ GNUNET_CREDENTIAL_verify_cancel (struct GNUNET_CREDENTIAL_Request *vr) * @param issuer_key the issuer public key * @param issuer_attribute the issuer attribute * @param subject_key the subject public key - * @param subject_attribute the attribute claimed by the subject + * @param credential_count number of credentials provided + * @param credentials subject credentials * @param proc function to call on result * @param proc_cls closure for processor * @return handle to the queued request @@ -378,25 +450,31 @@ GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle, const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key, const char *issuer_attribute, const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key, - const char *subject_attribute, - GNUNET_CREDENTIAL_VerifyResultProcessor proc, + uint32_t credential_count, + const struct GNUNET_CREDENTIAL_Credential *credentials, + GNUNET_CREDENTIAL_CredentialResultProcessor proc, void *proc_cls) { /* IPC to shorten credential names, return shorten_handle */ struct VerifyMessage *v_msg; struct GNUNET_CREDENTIAL_Request *vr; size_t nlen; + size_t clen; - if (NULL == issuer_attribute || NULL == subject_attribute) + if (NULL == issuer_attribute || NULL == credentials) { GNUNET_break (0); return NULL; } + + clen = GNUNET_CREDENTIAL_credentials_get_size (credential_count, + credentials); + //DEBUG LOG LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying to verify `%s' in CREDENTIAL\n", issuer_attribute); - nlen = strlen (issuer_attribute) + strlen (subject_attribute) + 1; + nlen = strlen (issuer_attribute) + 1 + clen; if (nlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*vr)) { GNUNET_break (0); @@ -412,17 +490,19 @@ GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle, GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY); v_msg->id = htonl (vr->r_id); v_msg->subject_key = *subject_key; + v_msg->c_count = htonl(credential_count); v_msg->issuer_key = *issuer_key; v_msg->issuer_attribute_len = htons(strlen(issuer_attribute)); - v_msg->subject_attribute_len = htons(strlen(subject_attribute)); GNUNET_memcpy (&v_msg[1], issuer_attribute, strlen (issuer_attribute)); - GNUNET_memcpy (((char*)&v_msg[1]) + strlen (issuer_attribute), - subject_attribute, - strlen (subject_attribute)); - GNUNET_CONTAINER_DLL_insert (handle->verify_head, - handle->verify_tail, + GNUNET_CREDENTIAL_credentials_serialize (credential_count, + credentials, + clen, + ((char*)&v_msg[1]) + + strlen (issuer_attribute) + 1); + GNUNET_CONTAINER_DLL_insert (handle->request_head, + handle->request_tail, vr); if (NULL != handle->mq) GNUNET_MQ_send_copy (handle->mq, diff --git a/src/credential/credential_misc.c b/src/credential/credential_misc.c index f1be433e0..7849e81e6 100644 --- a/src/credential/credential_misc.c +++ b/src/credential/credential_misc.c @@ -105,6 +105,7 @@ GNUNET_CREDENTIAL_credential_from_string (const char* s) GNUNET_memcpy (&cred[1], name, strlen (name)+1); + cred->issuer_attribute_len = strlen ((char*)&cred[1]); cred->issuer_attribute = (char*)&cred[1]; return cred; } diff --git a/src/credential/credential_serialization.c b/src/credential/credential_serialization.c index 0586e6baa..76bf491c9 100644 --- a/src/credential/credential_serialization.c +++ b/src/credential/credential_serialization.c @@ -138,6 +138,121 @@ GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len, } return GNUNET_OK; } + + +/** + * Calculate how many bytes we will need to serialize + * the credentials + * + * @param c_count number of credential entries + * @param cd a #GNUNET_CREDENTIAL_Credential + * @return the required size to serialize + */ +size_t +GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count, + const struct GNUNET_CREDENTIAL_Credential *cd) +{ + unsigned int i; + size_t ret; + + ret = sizeof (struct CredentialEntry) * (c_count); + + for (i=0; i= ret); + ret += cd[i].issuer_attribute_len; + } + return ret; +} +/** + * Serizalize the given credentials + * + * @param c_count number of credential entries + * @param cd a #GNUNET_CREDENTIAL_Credential + * @param dest_size size of the destination + * @param dest where to store the result + * @return the size of the data, -1 on failure + */ +ssize_t +GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count, + const struct GNUNET_CREDENTIAL_Credential *cd, + size_t dest_size, + char *dest) +{ + struct CredentialEntry c_rec; + unsigned int i; + size_t off; + + off = 0; + for (i=0;i dest_size) + return -1; + GNUNET_memcpy (&dest[off], + &c_rec, + sizeof (c_rec)); + off += sizeof (c_rec); + if (off + cd[i].issuer_attribute_len > dest_size) + return -1; + GNUNET_memcpy (&dest[off], + cd[i].issuer_attribute, + cd[i].issuer_attribute_len); + off += cd[i].issuer_attribute_len; + } + + return off; +} + + + +/** + * Deserialize the given destination + * + * @param len size of the serialized creds + * @param src the serialized data + * @param c_count the number of credential entries + * @param cd where to put the credential data + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +int +GNUNET_CREDENTIAL_credentials_deserialize (size_t len, + const char *src, + unsigned int c_count, + struct GNUNET_CREDENTIAL_Credential *cd) +{ + struct CredentialEntry c_rec; + unsigned int i; + size_t off; + + off = 0; + for (i=0;i len) + return GNUNET_SYSERR; + GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec)); + cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len); + cd[i].issuer_key = c_rec.issuer_key; + cd[i].subject_key = c_rec.subject_key; + cd[i].signature = c_rec.signature; + cd[i].expiration.abs_value_us = ntohl((uint32_t) c_rec.expiration); + off += sizeof (c_rec); + if (off + cd[i].issuer_attribute_len > len) + return GNUNET_SYSERR; + cd[i].issuer_attribute = &src[off]; + off += cd[i].issuer_attribute_len; + } + return GNUNET_OK; +} + + + /** * Calculate how many bytes we will need to serialize * the given delegation chain and credential @@ -158,7 +273,6 @@ GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count, size_t ret; ret = sizeof (struct ChainEntry) * (d_count); - ret += sizeof (struct CredentialEntry) * (c_count); for (i=0; i= ret); ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len; } - for (i=0; i= ret); - ret += cd[i].issuer_attribute_len; - } + return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd); return ret; } @@ -195,7 +305,6 @@ GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count, char *dest) { struct ChainEntry rec; - struct CredentialEntry c_rec; unsigned int i; size_t off; @@ -227,30 +336,10 @@ GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count, dd[i].subject_attribute_len); off += dd[i].subject_attribute_len; } - for (i=0;i dest_size) - return -1; - GNUNET_memcpy (&dest[off], - &c_rec, - sizeof (c_rec)); - off += sizeof (c_rec); - if (off + cd[i].issuer_attribute_len > dest_size) - return -1; - GNUNET_memcpy (&dest[off], - cd[i].issuer_attribute, - cd[i].issuer_attribute_len); - off += cd[i].issuer_attribute_len; - } - - return off; + return off+GNUNET_CREDENTIAL_credentials_serialize (c_count, + cd, + dest_size-off, + &dest[off]); } @@ -274,7 +363,6 @@ GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len, struct GNUNET_CREDENTIAL_Credential *cd) { struct ChainEntry rec; - struct CredentialEntry c_rec; unsigned int i; size_t off; @@ -298,26 +386,11 @@ GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len, dd[i].subject_attribute = &src[off]; off += dd[i].subject_attribute_len; } - for (i=0;i len) - return GNUNET_SYSERR; - GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec)); - cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len); - cd[i].issuer_key = c_rec.issuer_key; - cd[i].subject_key = c_rec.subject_key; - cd[i].signature = c_rec.signature; - cd[i].expiration.abs_value_us = ntohl((uint32_t) c_rec.expiration); - off += sizeof (c_rec); - if (off + cd[i].issuer_attribute_len > len) - return GNUNET_SYSERR; - cd[i].issuer_attribute = &src[off]; - off += cd[i].issuer_attribute_len; - } - return GNUNET_OK; + return GNUNET_CREDENTIAL_credentials_deserialize (len-off, + &src[off], + c_count, + cd); } - - int GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred, char **data) diff --git a/src/credential/credential_serialization.h b/src/credential/credential_serialization.h index eb1327f34..b870d47dc 100644 --- a/src/credential/credential_serialization.h +++ b/src/credential/credential_serialization.h @@ -130,6 +130,23 @@ GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len, struct GNUNET_CREDENTIAL_Delegation *dd, unsigned int c_count, struct GNUNET_CREDENTIAL_Credential *cd); + size_t + GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count, + const struct GNUNET_CREDENTIAL_Credential *cd); + +ssize_t +GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count, + const struct GNUNET_CREDENTIAL_Credential *cd, + size_t dest_size, + char *dest); + + +int +GNUNET_CREDENTIAL_credentials_deserialize (size_t len, + const char *src, + unsigned int c_count, + struct GNUNET_CREDENTIAL_Credential *cd); + int GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred, diff --git a/src/credential/gnunet-credential.c b/src/credential/gnunet-credential.c index b31c2f66e..fb7bdb7f8 100644 --- a/src/credential/gnunet-credential.c +++ b/src/credential/gnunet-credential.c @@ -54,6 +54,11 @@ static struct GNUNET_TIME_Relative timeout; */ static struct GNUNET_CREDENTIAL_Request *verify_request; +/** + * Handle to collect request + */ +static struct GNUNET_CREDENTIAL_Request *collect_request; + /** * Task scheduled to handle timeout. */ @@ -91,9 +96,9 @@ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey; static char *issuer_key; /** - * Issuer ego + * ego */ -static char *issuer_ego_name; +static char *ego_name; /** * Issuer attribute @@ -110,6 +115,10 @@ static uint32_t verify; */ static uint32_t create_cred; +/** + * Collect mode + */ +static uint32_t collect; /** * Task run on shutdown. Cleans up everything. @@ -149,6 +158,39 @@ do_timeout (void *cls) GNUNET_SCHEDULER_shutdown (); } +/** + * Function called with the result of a Credential lookup. + * + * @param cls the 'const char *' name that was resolved + * @param cd_count number of records returned + * @param cd array of @a cd_count records with the results + */ +static void +handle_collect_result (void *cls, + unsigned int d_count, + struct GNUNET_CREDENTIAL_Delegation *dc, + unsigned int c_count, + struct GNUNET_CREDENTIAL_Credential *cred) +{ + int i; + char* line; + + verify_request = NULL; + if (NULL != cred) + { + for (i=0;iissuer_attribute); + tok = strtok(NULL, ","); + GNUNET_free (cred); + } verify_request = GNUNET_CREDENTIAL_verify(credential, &issuer_pkey, issuer_attr, //TODO argument &subject_pkey, - subject_credential, + count, + credentials, &handle_verify_result, NULL); + for (i=0;i #include #include #include #include -#include "gnunet_gns_service.h" - - #define GNUNET_CREDENTIAL_MAX_LENGTH 255 @@ -311,6 +307,16 @@ struct VerifyRequestHandle */ uint64_t pending_lookups; + /** + * Credential iterator + */ + struct GNUNET_NAMESTORE_ZoneIterator *cred_collection_iter; + + /** + * Collect task + */ + struct GNUNET_SCHEDULER_Task *collect_next_task; + }; @@ -335,6 +341,11 @@ static struct GNUNET_STATISTICS_Handle *statistics; static struct GNUNET_GNS_Handle *gns; +/** + * Handle to namestore service + */ +static struct GNUNET_NAMESTORE_Handle *namestore; + static void cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry) { @@ -444,6 +455,11 @@ shutdown_task (void *cls) GNUNET_GNS_disconnect (gns); gns = NULL; } + if (NULL != namestore) + { + GNUNET_NAMESTORE_disconnect (namestore); + namestore = NULL; + } if (NULL != statistics) { GNUNET_STATISTICS_destroy (statistics, @@ -453,42 +469,7 @@ shutdown_task (void *cls) } -/** - * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY message - * - * @param cls client sending the message - * @param v_msg message of type `struct VerifyMessage` - * @return #GNUNET_OK if @a v_msg is well-formed - */ -static int -check_verify (void *cls, - const struct VerifyMessage *v_msg) -{ - size_t msg_size; - const char* attrs; - msg_size = ntohs (v_msg->header.size); - if (msg_size < sizeof (struct VerifyMessage)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if ((ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH) || - (ntohs (v_msg->subject_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - attrs = (const char *) &v_msg[1]; - - if ( ('\0' != attrs[ntohs(v_msg->header.size) - sizeof (struct VerifyMessage) - 1]) || - (strlen (attrs) > GNUNET_CREDENTIAL_MAX_LENGTH * 2) ) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} /** * Send. @@ -499,7 +480,7 @@ static void send_lookup_response (struct VerifyRequestHandle *vrh) { struct GNUNET_MQ_Envelope *env; - struct VerifyResultMessage *rmsg; + struct DelegationChainResultMessage *rmsg; struct DelegationChainEntry *dce; struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size]; struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size]; @@ -792,21 +773,14 @@ backward_resolution (void* cls, * @param rd the record data */ static void -handle_credential_query (void* cls, - uint32_t rd_count, - const struct GNUNET_GNSRECORD_Data *rd) +delegation_chain_resolution_start (void* cls) { struct VerifyRequestHandle *vrh = cls; struct DelegationSetQueueEntry *ds_entry; - struct GNUNET_CREDENTIAL_Credential *crd; struct CredentialRecordEntry *cr_entry; - int cred_record_count; - int i; - vrh->lookup_request = NULL; - cred_record_count = 0; - if (0 == rd_count) + if (0 == vrh->cred_chain_size) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No credentials found\n"); @@ -814,31 +788,13 @@ handle_credential_query (void* cls, return; } - for (i=0; i < rd_count; i++) + for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = cr_entry->next) { - if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type) - continue; - cred_record_count++; - crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data, - rd[i].data_size); - if (NULL == crd) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid credential found\n"); - continue; - } - cr_entry = GNUNET_new (struct CredentialRecordEntry); - cr_entry->credential = crd; - GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head, - vrh->cred_chain_tail, - cr_entry); - vrh->cred_chain_size++; - - if (0 != memcmp (&crd->issuer_key, + if (0 != memcmp (&cr_entry->credential->issuer_key, &vrh->issuer_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) continue; - if (0 != strcmp (crd->issuer_attribute, vrh->issuer_attribute)) + if (0 != strcmp (cr_entry->credential->issuer_attribute, vrh->issuer_attribute)) continue; //Found match prematurely send_lookup_response (vrh); @@ -878,6 +834,40 @@ handle_credential_query (void* cls, ds_entry); } +/** + * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY message + * + * @param cls client sending the message + * @param v_msg message of type `struct VerifyMessage` + * @return #GNUNET_OK if @a v_msg is well-formed + */ +static int +check_verify (void *cls, + const struct VerifyMessage *v_msg) +{ + size_t msg_size; + const char* attr; + + msg_size = ntohs (v_msg->header.size); + if (msg_size < sizeof (struct VerifyMessage)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + attr = (const char *) &v_msg[1]; + + if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} /** * Handle Credential verification requests from client @@ -890,12 +880,11 @@ static void handle_verify (void *cls, const struct VerifyMessage *v_msg) { - char attrs[GNUNET_CREDENTIAL_MAX_LENGTH*2 + 1]; + char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1]; char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1]; - char subject_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1 + 4]; struct VerifyRequestHandle *vrh; struct GNUNET_SERVICE_Client *client = cls; - char *attrptr = attrs; + char *attrptr = attr; const char *utf_in; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -904,12 +893,8 @@ handle_verify (void *cls, utf_in = (const char *) &v_msg[1]; GNUNET_STRINGS_utf8_tolower (utf_in, attrptr); - GNUNET_memcpy (issuer_attribute, attrs, ntohs (v_msg->issuer_attribute_len)); + GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len)); issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0'; - GNUNET_memcpy (subject_attribute, attrs+strlen(issuer_attribute), ntohs (v_msg->subject_attribute_len)); - strcpy (subject_attribute+ntohs (v_msg->subject_attribute_len), - ".gnu"); - subject_attribute[ntohs (v_msg->subject_attribute_len)+4] = '\0'; vrh = GNUNET_new (struct VerifyRequestHandle); GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh); vrh->client = client; @@ -917,14 +902,169 @@ handle_verify (void *cls, vrh->issuer_key = v_msg->issuer_key; vrh->subject_key = v_msg->subject_key; vrh->issuer_attribute = GNUNET_strdup (issuer_attribute); - - if (NULL == subject_attribute) + if (NULL == issuer_attribute) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No subject attribute provided!\n"); + "No issuer attribute provided!\n"); + send_lookup_response (vrh); + return; + } + /** + * First, collect credentials + * TODO: cleanup! + */ + uint32_t credentials_count = ntohl(v_msg->c_count); + int i; + uint32_t credential_data_size = ntohs (v_msg->header.size) + - sizeof (struct VerifyMessage) + - ntohs (v_msg->issuer_attribute_len) + - 1; + struct GNUNET_CREDENTIAL_Credential credentials[credentials_count]; + char *credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1; + struct CredentialRecordEntry *cr_entry; + if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize (credential_data_size, + credential_data, + credentials_count, + credentials)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Cannot deserialize credentials!\n"); send_lookup_response (vrh); return; } + + for (i=0;icredential = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + + strlen (credentials[i].issuer_attribute) + 1); + GNUNET_memcpy (cr_entry->credential, + &credentials[i], + sizeof (struct GNUNET_CREDENTIAL_Credential)); + GNUNET_memcpy (&cr_entry->credential[1], + credentials[i].issuer_attribute, + strlen (credentials[i].issuer_attribute)); + cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1]; + GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head, + vrh->cred_chain_tail, + cr_entry); + vrh->cred_chain_size++; + } + + delegation_chain_resolution_start (vrh); + +} + +/** + * We encountered an error while collecting + */ +static void +handle_cred_collection_error_cb (void *cls) +{ + struct VerifyRequestHandle *vrh = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got disconnected from namestore database.\n"); + vrh->cred_collection_iter = NULL; + send_lookup_response (vrh); +} + +static void +collect_next (void *cls) +{ + struct VerifyRequestHandle *vrh = cls; + vrh->collect_next_task = NULL; + GNUNET_assert (NULL != vrh->cred_collection_iter); + GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter); +} + +/** + * Store credential + */ +static void +handle_cred_collection_cb (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, + const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct VerifyRequestHandle *vrh = cls; + struct GNUNET_CREDENTIAL_Credential *crd; + struct CredentialRecordEntry *cr_entry; + int cred_record_count; + int i; + + cred_record_count = 0; + for (i=0; i < rd_count; i++) + { + if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type) + continue; + cred_record_count++; + crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data, + rd[i].data_size); + if (NULL == crd) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Invalid credential found\n"); + continue; + } + cr_entry = GNUNET_new (struct CredentialRecordEntry); + cr_entry->credential = crd; + GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head, + vrh->cred_chain_tail, + cr_entry); + vrh->cred_chain_size++; + } + vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next, + vrh); +} + +/** + * We encountered an error while collecting + */ +static void +handle_cred_collection_finished_cb (void *cls) +{ + struct VerifyRequestHandle *vrh = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Done collecting credentials.\n"); + vrh->cred_collection_iter = NULL; + delegation_chain_resolution_start (vrh); +} + +/** + * Handle Credential collection requests from client + * + * @param cls the closure + * @param client the client + * @param message the message + */ +static void +handle_collect (void *cls, + const struct CollectMessage *c_msg) +{ + char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1]; + char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1]; + struct VerifyRequestHandle *vrh; + struct GNUNET_SERVICE_Client *client = cls; + char *attrptr = attr; + const char *utf_in; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received COLLECT message\n"); + + utf_in = (const char *) &c_msg[1]; + GNUNET_STRINGS_utf8_tolower (utf_in, attrptr); + + GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len)); + issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0'; + vrh = GNUNET_new (struct VerifyRequestHandle); + GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh); + vrh->client = client; + vrh->request_id = c_msg->id; + vrh->issuer_key = c_msg->issuer_key; + GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key, + &vrh->subject_key); + vrh->issuer_attribute = GNUNET_strdup (issuer_attribute); + if (NULL == issuer_attribute) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -933,22 +1073,57 @@ handle_verify (void *cls, return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Looking up %s\n", - subject_attribute); + "Getting credentials for subject\n"); /** * First, get attribute from subject */ - vrh->lookup_request = GNUNET_GNS_lookup (gns, - subject_attribute, - &v_msg->subject_key, //subject_pkey, - GNUNET_GNSRECORD_TYPE_CREDENTIAL, - GNUNET_GNS_LO_DEFAULT, - NULL, //shorten_key, always NULL - &handle_credential_query, - vrh); + vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore, + &c_msg->subject_key, + &handle_cred_collection_error_cb, + vrh, + &handle_cred_collection_cb, + vrh, + &handle_cred_collection_finished_cb, + vrh); } +/** + * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT message + * + * @param cls client sending the message + * @param v_msg message of type `struct CollectMessage` + * @return #GNUNET_OK if @a v_msg is well-formed + */ +static int +check_collect (void *cls, + const struct CollectMessage *c_msg) +{ + size_t msg_size; + const char* attr; + + msg_size = ntohs (c_msg->header.size); + if (msg_size < sizeof (struct CollectMessage)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + attr = (const char *) &c_msg[1]; + + if ( ('\0' != attr[ntohs(c_msg->header.size) - sizeof (struct CollectMessage) - 1]) || + (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) ) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + /** * One of our clients disconnected, clean up after it. * @@ -1003,6 +1178,12 @@ run (void *cls, fprintf (stderr, _("Failed to connect to GNS\n")); } + namestore = GNUNET_NAMESTORE_connect (c); + if (NULL == namestore) + { + fprintf (stderr, + _("Failed to connect to namestore\n")); + } statistics = GNUNET_STATISTICS_create ("credential", c); GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); @@ -1023,6 +1204,10 @@ GNUNET_SERVICE_MAIN GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY, struct VerifyMessage, NULL), + GNUNET_MQ_hd_var_size (collect, + GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT, + struct CollectMessage, + NULL), GNUNET_MQ_handler_end()); /* end of gnunet-service-credential.c */ diff --git a/src/credential/plugin_rest_credential.c b/src/credential/plugin_rest_credential.c index 651de0075..f13e26cd4 100644 --- a/src/credential/plugin_rest_credential.c +++ b/src/credential/plugin_rest_credential.c @@ -492,7 +492,8 @@ verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle, &handle->issuer_key, handle->issuer_attr, &handle->subject_key, - handle->subject_attr, + 0, + NULL,//TODOhandle->subject_attr, &handle_verify_response, handle); diff --git a/src/credential/test_credential_collect.sh b/src/credential/test_credential_collect.sh new file mode 100755 index 000000000..6c713063f --- /dev/null +++ b/src/credential/test_credential_collect.sh @@ -0,0 +1,47 @@ +#!/bin/bash +trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f` + +# (1) PKEY1.user -> PKEY2.resu.user +# (2) PKEY2.resu -> PKEY3 +# (3) PKEY3.user -> PKEY4 + + +which timeout &> /dev/null && DO_TIMEOUT="timeout 30" + +TEST_ATTR="test" +TEST_ATTR2="test2" +gnunet-arm -s -c test_credential_lookup.conf +gnunet-identity -C testissuer -c test_credential_lookup.conf +gnunet-identity -C testsubject -c test_credential_lookup.conf +SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}') +ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}') +#TODO1 Get credential and store it with subject (3) +CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf` +$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf +CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR2 --ttl=5m -c test_credential_lookup.conf` +$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c2 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf +CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --ego=testsubject -c test_credential_lookup.conf | paste -d, -s` +echo $CREDS +RES=$? +gnunet-arm -e -c test_credential_lookup.conf + +if test $? != 0 +then + echo "Error collecting..." + exit 1 +fi + diff --git a/src/credential/test_credential_lookup.conf b/src/credential/test_credential_lookup.conf index 7aa193abd..93b4864d9 100644 --- a/src/credential/test_credential_lookup.conf +++ b/src/credential/test_credential_lookup.conf @@ -11,7 +11,7 @@ PLUGINS = [credential] AUTOSTART = YES -#PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/credlog +PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/credlog [rest] #PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog diff --git a/src/credential/test_credential_verify.sh b/src/credential/test_credential_verify.sh index 6d69e337b..d042bcfe6 100755 --- a/src/credential/test_credential_verify.sh +++ b/src/credential/test_credential_verify.sh @@ -57,8 +57,11 @@ CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY -- # Alice stores the credential under "mygnunetcreds" gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf +CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, -s` + +echo gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=\'$CREDS\' -c test_credential_lookup.conf #TODO2 Add -z swich like in gnunet-gns -RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf` +gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential="$CREDS" -c test_credential_lookup.conf #TODO cleanup properly diff --git a/src/include/gnunet_credential_service.h b/src/include/gnunet_credential_service.h index 906163c14..d04c0a253 100644 --- a/src/include/gnunet_credential_service.h +++ b/src/include/gnunet_credential_service.h @@ -235,7 +235,7 @@ GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle); * @param c_count the number of credentials found * @param credential the credentials */ -typedef void (*GNUNET_CREDENTIAL_VerifyResultProcessor) (void *cls, +typedef void (*GNUNET_CREDENTIAL_CredentialResultProcessor) (void *cls, unsigned int d_count, struct GNUNET_CREDENTIAL_Delegation *delegation_chain, unsigned int c_count, @@ -286,10 +286,19 @@ GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle, const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key, const char *issuer_attribute, const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key, - const char *subject_attribute, - GNUNET_CREDENTIAL_VerifyResultProcessor proc, + uint32_t credential_count, + const struct GNUNET_CREDENTIAL_Credential *credentials, + GNUNET_CREDENTIAL_CredentialResultProcessor proc, void *proc_cls); +struct GNUNET_CREDENTIAL_Request* +GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle, + const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key, + const char *issuer_attribute, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key, + GNUNET_CREDENTIAL_CredentialResultProcessor proc, + void *proc_cls); + /** * Delegate an attribute * diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 596196311..cf26f1727 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -2616,6 +2616,10 @@ extern "C" #define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT 972 +#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT 973 + +#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT 974 + /******************************************************************************/ -- 2.25.1