X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fcredential%2Fgnunet-service-credential.c;h=be75e485ec375f65b2e573615e93fe7f1f9ad95c;hb=1eb75229e02e5bd678f1a99eae9a6062330ecb46;hp=8f7d71b28773e4907ecb6c2a4eb2200eff9d7bfa;hpb=a80e5610fe689631da94242e05f5ad85b21b6b4d;p=oweals%2Fgnunet.git diff --git a/src/credential/gnunet-service-credential.c b/src/credential/gnunet-service-credential.c index 8f7d71b28..be75e485e 100644 --- a/src/credential/gnunet-service-credential.c +++ b/src/credential/gnunet-service-credential.c @@ -31,23 +31,32 @@ #include "gnunet_protocols.h" #include "gnunet_signatures.h" -// For Looking up GNS request #include #include #include #include #include -#include "gnunet_gns_service.h" - - #define GNUNET_CREDENTIAL_MAX_LENGTH 255 struct VerifyRequestHandle; -struct GNUNET_CREDENTIAL_DelegationChainEntry +struct DelegationSetQueueEntry; + + +struct DelegationChainEntry { + /** + * DLL + */ + struct DelegationChainEntry *next; + + /** + * DLL + */ + struct DelegationChainEntry *prev; + /** * The issuer */ @@ -83,22 +92,21 @@ struct CredentialRecordEntry * DLL */ struct CredentialRecordEntry *prev; - - + /** - * Payload + * Number of references in delegation chains */ - struct GNUNET_CREDENTIAL_CredentialRecordData *data; + uint32_t refcount; /** - * Size + * Payload */ - uint64_t data_size; + struct GNUNET_CREDENTIAL_Credential *credential; }; /** - * DLL for delegations - Used as a queue - * Insert tail - Pop head + * DLL used for delegations + * Used for OR delegations */ struct DelegationQueueEntry { @@ -113,16 +121,43 @@ struct DelegationQueueEntry struct DelegationQueueEntry *prev; /** - * Children of this attribute + * Sets under this Queue */ - struct DelegationQueueEntry *children_head; + struct DelegationSetQueueEntry *set_entries_head; /** - * Children of this attribute + * Sets under this Queue */ - struct DelegationQueueEntry *children_tail; + struct DelegationSetQueueEntry *set_entries_tail; /** + * Parent set + */ + struct DelegationSetQueueEntry *parent_set; + + /** + * Required solutions + */ + uint32_t required_solutions; +}; + +/** + * DLL for delegation sets + * Used for AND delegation set + */ +struct DelegationSetQueueEntry +{ + /** + * DLL + */ + struct DelegationSetQueueEntry *next; + + /** + * DLL + */ + struct DelegationSetQueueEntry *prev; + + /** * GNS handle */ struct GNUNET_GNS_LookupRequest *lookup_request; @@ -142,6 +177,21 @@ struct DelegationQueueEntry */ struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key; + /** + * Queue entries of this set + */ + struct DelegationQueueEntry *queue_entries_head; + + /** + * Queue entries of this set + */ + struct DelegationQueueEntry *queue_entries_tail; + + /** + * Parent QueueEntry + */ + struct DelegationQueueEntry *parent_queue_entry; + /** * Issuer attribute delegated to */ @@ -161,16 +211,12 @@ struct DelegationQueueEntry * Still to resolve delegation as string */ char *unresolved_attribute_delegation; - + /** * The delegation chain entry */ - struct GNUNET_CREDENTIAL_DelegationChainEntry *delegation_chain_entry; + struct DelegationChainEntry *delegation_chain_entry; - /** - * Delegation chain length until now - */ - uint32_t d_count; }; @@ -194,18 +240,32 @@ struct VerifyRequestHandle * Handle to the requesting client */ struct GNUNET_SERVICE_Client *client; - + /** * GNS handle */ struct GNUNET_GNS_LookupRequest *lookup_request; + /** + * Size of delegation tree + */ + uint32_t delegation_chain_size; + + /** + * Children of this attribute + */ + struct DelegationChainEntry *delegation_chain_head; + + /** + * Children of this attribute + */ + struct DelegationChainEntry *delegation_chain_tail; /** * Issuer public key */ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key; - + /** * Issuer attribute */ @@ -217,54 +277,49 @@ struct VerifyRequestHandle struct GNUNET_CRYPTO_EcdsaPublicKey subject_key; /** - * Credential Chain + * Credential DLL */ struct CredentialRecordEntry *cred_chain_head; /** - * Credential Chain + * Credential DLL */ struct CredentialRecordEntry *cred_chain_tail; /** - * Delegation Queue + * Credential DLL size */ - struct DelegationQueueEntry *chain_start; - + uint32_t cred_chain_size; + /** - * Delegation Queue + * Root Delegation Set */ - struct DelegationQueueEntry *chain_end; - + struct DelegationSetQueueEntry *root_set; + /** * Current Delegation Pointer */ struct DelegationQueueEntry *current_delegation; /** - * The found credential - */ - struct GNUNET_CREDENTIAL_CredentialRecordData *credential; - - /** - * Length of the credential + * request id */ - uint32_t credential_size; + uint32_t request_id; /** - * Length of found delegation chain + * Pending lookups */ - uint32_t d_count; + uint64_t pending_lookups; /** - * request id + * Credential iterator */ - uint32_t request_id; + struct GNUNET_NAMESTORE_ZoneIterator *cred_collection_iter; /** - * Pending lookups + * Collect task */ - uint64_t pending_lookups; + struct GNUNET_SCHEDULER_Task *collect_next_task; }; @@ -290,60 +345,76 @@ 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_queue (struct DelegationQueueEntry *dq_entry) +cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry) { - struct DelegationQueueEntry *child; - if (NULL == dq_entry) + struct DelegationQueueEntry *dq_entry; + struct DelegationSetQueueEntry *child; + + if (NULL == ds_entry) return; - for (child = dq_entry->children_head; NULL != child; child = dq_entry->children_head) + for (dq_entry = ds_entry->queue_entries_head; + NULL != dq_entry; + dq_entry = ds_entry->queue_entries_head) { - GNUNET_CONTAINER_DLL_remove (dq_entry->children_head, - dq_entry->children_tail, - child); - cleanup_delegation_queue (child); + GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head, + ds_entry->queue_entries_tail, + dq_entry); + for (child = dq_entry->set_entries_head; + NULL != child; + child = dq_entry->set_entries_head) + { + GNUNET_CONTAINER_DLL_remove (dq_entry->set_entries_head, + dq_entry->set_entries_tail, + child); + cleanup_delegation_set (child); + } + GNUNET_free (dq_entry); } - if (NULL != dq_entry->issuer_key) - GNUNET_free (dq_entry->issuer_key); - if (NULL != dq_entry->lookup_attribute) - GNUNET_free (dq_entry->lookup_attribute); - if (NULL != dq_entry->issuer_attribute) - GNUNET_free (dq_entry->issuer_attribute); - if (NULL != dq_entry->unresolved_attribute_delegation) - GNUNET_free (dq_entry->unresolved_attribute_delegation); - if (NULL != dq_entry->attr_trailer) - GNUNET_free (dq_entry->attr_trailer); - if (NULL != dq_entry->lookup_request) + if (NULL != ds_entry->issuer_key) + GNUNET_free (ds_entry->issuer_key); + if (NULL != ds_entry->lookup_attribute) + GNUNET_free (ds_entry->lookup_attribute); + if (NULL != ds_entry->issuer_attribute) + GNUNET_free (ds_entry->issuer_attribute); + if (NULL != ds_entry->unresolved_attribute_delegation) + GNUNET_free (ds_entry->unresolved_attribute_delegation); + if (NULL != ds_entry->attr_trailer) + GNUNET_free (ds_entry->attr_trailer); + if (NULL != ds_entry->lookup_request) { - GNUNET_GNS_lookup_cancel (dq_entry->lookup_request); - dq_entry->lookup_request = NULL; + GNUNET_GNS_lookup_cancel (ds_entry->lookup_request); + ds_entry->lookup_request = NULL; } - if (NULL != dq_entry->delegation_chain_entry) + if (NULL != ds_entry->delegation_chain_entry) { - if (NULL != dq_entry->delegation_chain_entry->subject_attribute) - GNUNET_free (dq_entry->delegation_chain_entry->subject_attribute); - if (NULL != dq_entry->delegation_chain_entry->issuer_attribute) - GNUNET_free (dq_entry->delegation_chain_entry->issuer_attribute); - GNUNET_free (dq_entry->delegation_chain_entry); + if (NULL != ds_entry->delegation_chain_entry->subject_attribute) + GNUNET_free (ds_entry->delegation_chain_entry->subject_attribute); + if (NULL != ds_entry->delegation_chain_entry->issuer_attribute) + GNUNET_free (ds_entry->delegation_chain_entry->issuer_attribute); + GNUNET_free (ds_entry->delegation_chain_entry); } - GNUNET_free (dq_entry); + GNUNET_free (ds_entry); } static void cleanup_handle (struct VerifyRequestHandle *vrh) { struct CredentialRecordEntry *cr_entry; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up...\n"); if (NULL != vrh->lookup_request) { GNUNET_GNS_lookup_cancel (vrh->lookup_request); vrh->lookup_request = NULL; } - if (NULL != vrh->credential) - GNUNET_free (vrh->credential); - cleanup_delegation_queue (vrh->chain_start); + cleanup_delegation_set (vrh->root_set); if (NULL != vrh->issuer_attribute) GNUNET_free (vrh->issuer_attribute); for (cr_entry = vrh->cred_chain_head; @@ -353,8 +424,8 @@ cleanup_handle (struct VerifyRequestHandle *vrh) GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head, vrh->cred_chain_tail, cr_entry); - if (NULL != cr_entry->data) - GNUNET_free (cr_entry->data); + if (NULL != cr_entry->credential); + GNUNET_free (cr_entry->credential); GNUNET_free (cr_entry); } GNUNET_free (vrh); @@ -371,7 +442,7 @@ shutdown_task (void *cls) { struct VerifyRequestHandle *vrh; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down!\n"); while (NULL != (vrh = vrh_head)) @@ -388,6 +459,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, @@ -397,42 +473,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. @@ -443,58 +484,93 @@ static void send_lookup_response (struct VerifyRequestHandle *vrh) { struct GNUNET_MQ_Envelope *env; - struct VerifyResultMessage *rmsg; - struct DelegationQueueEntry *dq_entry; - size_t size = vrh->credential_size; - struct GNUNET_CREDENTIAL_Delegation dd[vrh->d_count]; - struct GNUNET_CREDENTIAL_Credential cred; + struct DelegationChainResultMessage *rmsg; + struct DelegationChainEntry *dce; + struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size]; + struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size]; + struct CredentialRecordEntry *cd; + struct CredentialRecordEntry *tmp; + size_t size; + int i; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending response\n"); - dq_entry = vrh->chain_end; - for (int i=0; id_count; i++) + dce = vrh->delegation_chain_head; + for (i=0;idelegation_chain_size;i++) { - dd[i].issuer_key = dq_entry->delegation_chain_entry->issuer_key; - dd[i].subject_key = dq_entry->delegation_chain_entry->subject_key; - dd[i].issuer_attribute = dq_entry->delegation_chain_entry->issuer_attribute; - dd[i].issuer_attribute_len = strlen (dq_entry->delegation_chain_entry->issuer_attribute)+1; + dd[i].issuer_key = dce->issuer_key; + dd[i].subject_key = dce->subject_key; + dd[i].issuer_attribute = dce->issuer_attribute; + dd[i].issuer_attribute_len = strlen (dce->issuer_attribute)+1; dd[i].subject_attribute_len = 0; - if (NULL != dq_entry->delegation_chain_entry->subject_attribute) + dd[i].subject_attribute = NULL; + if (NULL != dce->subject_attribute) { - dd[i].subject_attribute = dq_entry->delegation_chain_entry->subject_attribute; - dd[i].subject_attribute_len = strlen(dq_entry->delegation_chain_entry->subject_attribute)+1; + dd[i].subject_attribute = dce->subject_attribute; + dd[i].subject_attribute_len = strlen(dce->subject_attribute)+1; } - dq_entry = dq_entry->parent; + dce = dce->next; } - /** + /** + * Remove all credentials not needed + */ + for (cd = vrh->cred_chain_head; NULL != cd;) + { + if (cd->refcount > 0) + { + cd = cd->next; + continue; + } + tmp = cd; + cd = cd->next; + GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head, + vrh->cred_chain_tail, + tmp); + GNUNET_free (tmp->credential); + GNUNET_free (tmp); + vrh->cred_chain_size--; + } + + /** * Get serialized record data * Append at the end of rmsg */ - cred.issuer_key = vrh->credential->issuer_key; - cred.subject_key = vrh->credential->subject_key; - cred.issuer_attribute_len = strlen((char*)&vrh->credential[1]); - cred.issuer_attribute = (char*)&vrh->credential[1]; - size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->d_count, + cd = vrh->cred_chain_head; + for (i=0;icred_chain_size;i++) + { + cred[i].issuer_key = cd->credential->issuer_key; + cred[i].subject_key = cd->credential->subject_key; + cred[i].issuer_attribute_len = strlen(cd->credential->issuer_attribute)+1; + cred[i].issuer_attribute = cd->credential->issuer_attribute; + cred[i].expiration = cd->credential->expiration; + cred[i].signature = cd->credential->signature; + cd = cd->next; + } + size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->delegation_chain_size, dd, - &cred); + vrh->cred_chain_size, + cred); env = GNUNET_MQ_msg_extra (rmsg, size, GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT); //Assign id so that client can find associated request rmsg->id = vrh->request_id; - rmsg->d_count = htonl (vrh->d_count); + rmsg->d_count = htonl (vrh->delegation_chain_size); + rmsg->c_count = htonl (vrh->cred_chain_size); - if (NULL != vrh->credential) + if (0 < vrh->cred_chain_size) rmsg->cred_found = htonl (GNUNET_YES); else rmsg->cred_found = htonl (GNUNET_NO); - GNUNET_assert (-1 != GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->d_count, - dd, - &cred, - size, - (char*)&rmsg[1])); + GNUNET_assert (-1 != + GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->delegation_chain_size, + dd, + vrh->cred_chain_size, + cred, + size, + (char*)&rmsg[1])); GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client), env); @@ -514,152 +590,197 @@ backward_resolution (void* cls, { struct VerifyRequestHandle *vrh; - struct GNUNET_CREDENTIAL_CredentialRecordData *cred; - const struct GNUNET_CREDENTIAL_AttributeRecordData *attr; + const struct GNUNET_CREDENTIAL_DelegationRecord *sets; struct CredentialRecordEntry *cred_pointer; - struct DelegationQueueEntry *current_delegation; + struct DelegationSetQueueEntry *current_set; + struct DelegationSetQueueEntry *ds_entry; + struct DelegationSetQueueEntry *tmp_set; struct DelegationQueueEntry *dq_entry; char *expanded_attr; char *lookup_attribute; int i; + int j; - current_delegation = cls; - current_delegation->lookup_request = NULL; - vrh = current_delegation->handle; + current_set = cls; + current_set->lookup_request = NULL; + vrh = current_set->handle; vrh->pending_lookups--; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got %d attrs\n", rd_count); + // Each OR for (i=0; i < rd_count; i++) { if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type) continue; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Found new attribute delegation. Creating new Job...\n"); - attr = rd[i].data; - dq_entry = GNUNET_new (struct DelegationQueueEntry); - if (NULL != current_delegation->attr_trailer) - { - if (rd[i].data_size == sizeof (struct GNUNET_CREDENTIAL_AttributeRecordData)) - { - GNUNET_asprintf (&expanded_attr, - "%s", - current_delegation->attr_trailer); + sets = rd[i].data; + struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)]; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Found new attribute delegation with %d sets. Creating new Job...\n", + ntohl (sets->set_count)); - } else { - GNUNET_asprintf (&expanded_attr, - "%s.%s", - (char*)&attr[1], - current_delegation->attr_trailer); - } + if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size), + (const char*)&sets[1], + ntohl(sets->set_count), + set)) + { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Expanded to %s\n", expanded_attr); - dq_entry->unresolved_attribute_delegation = expanded_attr; - } else { - if (rd[i].data_size > sizeof (struct GNUNET_CREDENTIAL_AttributeRecordData)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Not Expanding %s\n", (char*)&attr[1]); - dq_entry->unresolved_attribute_delegation = GNUNET_strdup ((char*)&attr[1]); - } + "Failed to deserialize!\n"); + continue; } - - //Add a credential chain entry - dq_entry->delegation_chain_entry = GNUNET_new (struct GNUNET_CREDENTIAL_DelegationChainEntry); - dq_entry->delegation_chain_entry->subject_key = attr->subject_key; - dq_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); - GNUNET_memcpy (dq_entry->issuer_key, - &attr->subject_key, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - if (rd[i].data_size > sizeof (struct GNUNET_CREDENTIAL_AttributeRecordData)) - dq_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup ((char*)&attr[1]); - dq_entry->delegation_chain_entry->issuer_key = *current_delegation->issuer_key; - dq_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_delegation->lookup_attribute); - - dq_entry->parent = current_delegation; - dq_entry->d_count = current_delegation->d_count + 1; - GNUNET_CONTAINER_DLL_insert (current_delegation->children_head, - current_delegation->children_tail, + dq_entry = GNUNET_new (struct DelegationQueueEntry); + dq_entry->required_solutions = ntohl(sets->set_count); + dq_entry->parent_set = current_set; + GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head, + current_set->queue_entries_tail, dq_entry); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Checking for cred match\n"); - /** - * Check if this delegation already matches one of our credentials - */ - for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL; - cred_pointer = cred_pointer->next) + // Each AND + for (j=0; jset_count); j++) { - cred = cred_pointer->data; - if(0 != memcmp (&attr->subject_key, - &cred_pointer->data->issuer_key, - sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) - continue; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Checking if %s matches %s\n", - dq_entry->unresolved_attribute_delegation, (char*)&cred[1]); + ds_entry = GNUNET_new (struct DelegationSetQueueEntry); + if (NULL != current_set->attr_trailer) + { + if (0 == set[j].subject_attribute_len) + { + GNUNET_asprintf (&expanded_attr, + "%s", + current_set->attr_trailer); + + } else { + GNUNET_asprintf (&expanded_attr, + "%s.%s", + set[j].subject_attribute, + current_set->attr_trailer); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Expanded to %s\n", expanded_attr); + ds_entry->unresolved_attribute_delegation = expanded_attr; + } else { + if (0 != set[j].subject_attribute_len) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Not Expanding %s\n", set[j].subject_attribute); + ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute); + } + } - if (0 != strcmp (dq_entry->unresolved_attribute_delegation, (char*)&cred[1])) + //Add a credential chain entry + ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry); + ds_entry->delegation_chain_entry->subject_key = set[j].subject_key; + ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); + GNUNET_memcpy (ds_entry->issuer_key, + &set[j].subject_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + if (0 < set[j].subject_attribute_len) + ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute); + ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key; + ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute); + + ds_entry->parent_queue_entry = dq_entry; //current_delegation; + GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head, + dq_entry->set_entries_tail, + ds_entry); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Checking for cred match\n"); + /** + * Check if this delegation already matches one of our credentials + */ + for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL; + cred_pointer = cred_pointer->next) + { + if(0 != memcmp (&set->subject_key, + &cred_pointer->credential->issuer_key, + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) + continue; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Checking if %s matches %s\n", + ds_entry->unresolved_attribute_delegation, + cred_pointer->credential->issuer_attribute); + + if (0 != strcmp (ds_entry->unresolved_attribute_delegation, + cred_pointer->credential->issuer_attribute)) + continue; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Found issuer\n"); + cred_pointer->refcount++; + //Backtrack + for (tmp_set = ds_entry; + NULL != tmp_set->parent_queue_entry; + tmp_set = tmp_set->parent_queue_entry->parent_set) + { + tmp_set->parent_queue_entry->required_solutions--; + if (NULL != tmp_set->delegation_chain_entry) + { + vrh->delegation_chain_size++; + GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head, + vrh->delegation_chain_tail, + tmp_set->delegation_chain_entry); + } + if (0 < tmp_set->parent_queue_entry->required_solutions) + break; + } + + if (NULL == tmp_set->parent_queue_entry) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "All solutions found\n"); + //Found match + send_lookup_response (vrh); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Not all solutions found yet.\n"); continue; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Found issuer\n"); - vrh->credential = GNUNET_malloc (cred_pointer->data_size); - memcpy (vrh->credential, - cred, - cred_pointer->data_size); - vrh->credential_size = cred_pointer->data_size; - vrh->chain_end = dq_entry; - vrh->d_count = dq_entry->d_count; - //Found match - send_lookup_response (vrh); - return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Building new lookup request from %s\n", + ds_entry->unresolved_attribute_delegation); + //Continue with backward resolution + char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1]; + strcpy (issuer_attribute_name, + ds_entry->unresolved_attribute_delegation); + char *next_attr = strtok (issuer_attribute_name, "."); + GNUNET_asprintf (&lookup_attribute, + "%s.gnu", + next_attr); + GNUNET_asprintf (&ds_entry->lookup_attribute, + "%s", + next_attr); + if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation)) + { + ds_entry->attr_trailer = NULL; + } else { + next_attr += strlen (next_attr) + 1; + ds_entry->attr_trailer = GNUNET_strdup (next_attr); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Looking up %s\n", ds_entry->lookup_attribute); + if (NULL != ds_entry->attr_trailer) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "%s still to go...\n", ds_entry->attr_trailer); + + vrh->pending_lookups++; + ds_entry->handle = vrh; + ds_entry->lookup_request = GNUNET_GNS_lookup (gns, + lookup_attribute, + ds_entry->issuer_key, //issuer_key, + GNUNET_GNSRECORD_TYPE_ATTRIBUTE, + GNUNET_GNS_LO_DEFAULT, + &backward_resolution, + ds_entry); + GNUNET_free (lookup_attribute); } - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Building new lookup request\n"); - //Continue with backward resolution - char issuer_attribute_name[strlen (dq_entry->unresolved_attribute_delegation)+1]; - strcpy (issuer_attribute_name, - dq_entry->unresolved_attribute_delegation); - char *next_attr = strtok (issuer_attribute_name, "."); - GNUNET_asprintf (&lookup_attribute, - "%s.gnu", - next_attr); - GNUNET_asprintf (&dq_entry->lookup_attribute, - "%s", - next_attr); - if (strlen (next_attr) == strlen (dq_entry->unresolved_attribute_delegation)) - { - dq_entry->attr_trailer = NULL; - } else { - next_attr += strlen (next_attr) + 1; - dq_entry->attr_trailer = GNUNET_strdup (next_attr); - } - - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Looking up %s\n", dq_entry->lookup_attribute); - if (NULL != dq_entry->attr_trailer) - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "%s still to go...\n", dq_entry->attr_trailer); - - vrh->pending_lookups++; - dq_entry->handle = vrh; - dq_entry->lookup_request = GNUNET_GNS_lookup (gns, - lookup_attribute, - dq_entry->issuer_key, //issuer_key, - GNUNET_GNSRECORD_TYPE_ATTRIBUTE, - GNUNET_GNS_LO_DEFAULT, - NULL, //shorten_key, always NULL - &backward_resolution, - dq_entry); - GNUNET_free (lookup_attribute); } if(0 == vrh->pending_lookups) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We are all out of attributes...\n"); send_lookup_response (vrh); return; @@ -676,56 +797,30 @@ 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 DelegationQueueEntry *dq_entry; - const struct GNUNET_CREDENTIAL_CredentialRecordData *crd; + struct DelegationSetQueueEntry *ds_entry; struct CredentialRecordEntry *cr_entry; - int cred_record_count; - int i; - vrh->lookup_request = NULL; - cred_record_count = 0; - for (i=0; i < rd_count; i++) + + if (0 == vrh->cred_chain_size) { - if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type) - continue; - cred_record_count++; - crd = rd[i].data; - if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL, - &crd->purpose, - &crd->signature, - &crd->issuer_key)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid credential found\n"); - continue; - } - cr_entry = GNUNET_new (struct CredentialRecordEntry); - cr_entry->data = GNUNET_malloc (rd[i].data_size); - memcpy (cr_entry->data, - crd, - rd[i].data_size); - cr_entry->data_size = rd[i].data_size; - GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head, - vrh->cred_chain_tail, - cr_entry); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No credentials found\n"); + send_lookup_response (vrh); + return; + } - if (0 != memcmp (&crd->issuer_key, + for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = cr_entry->next) + { + if (0 != memcmp (&cr_entry->credential->issuer_key, &vrh->issuer_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) continue; - if (0 != strcmp ((char*)&crd[1], vrh->issuer_attribute)) + if (0 != strcmp (cr_entry->credential->issuer_attribute, vrh->issuer_attribute)) continue; - vrh->credential = GNUNET_malloc (rd[i].data_size); - memcpy (vrh->credential, - rd[i].data, - rd[i].data_size); - vrh->credential_size = rd[i].data_size; - vrh->chain_end = NULL; + cr_entry->refcount++; //Found match prematurely send_lookup_response (vrh); return; @@ -741,30 +836,62 @@ handle_credential_query (void* cls, vrh->issuer_attribute); strcpy (issuer_attribute_name + strlen (vrh->issuer_attribute), ".gnu"); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up %s\n", issuer_attribute_name); - dq_entry = GNUNET_new (struct DelegationQueueEntry); - dq_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); - memcpy (dq_entry->issuer_key, + ds_entry = GNUNET_new (struct DelegationSetQueueEntry); + ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); + memcpy (ds_entry->issuer_key, &vrh->issuer_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - dq_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute); - dq_entry->handle = vrh; - dq_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute); - dq_entry->d_count = 0; - vrh->chain_start = dq_entry; + ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute); + ds_entry->handle = vrh; + ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute); + vrh->root_set = ds_entry; vrh->pending_lookups = 1; //Start with backward resolution - dq_entry->lookup_request = GNUNET_GNS_lookup (gns, + ds_entry->lookup_request = GNUNET_GNS_lookup (gns, issuer_attribute_name, &vrh->issuer_key, //issuer_key, GNUNET_GNSRECORD_TYPE_ATTRIBUTE, GNUNET_GNS_LO_DEFAULT, - NULL, //shorten_key, always NULL &backward_resolution, - dq_entry); + 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 @@ -777,26 +904,24 @@ static void handle_verify (void *cls, const struct VerifyMessage *v_msg) { - char attrs[GNUNET_CREDENTIAL_MAX_LENGTH*2 + 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; + struct CredentialRecordEntry *cr_entry; + uint32_t credentials_count; + uint32_t credential_data_size; + int i; + char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1]; + char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1]; + char *attrptr = attr; + char *credential_data; const char *utf_in; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received VERIFY message\n"); - 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; @@ -804,14 +929,167 @@ 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! + */ + credentials_count = ntohl(v_msg->c_count); + 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]; + credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1; + 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) + + credentials[i].issuer_attribute_len); + GNUNET_memcpy (cr_entry->credential, + &credentials[i], + sizeof (struct GNUNET_CREDENTIAL_Credential)); + GNUNET_memcpy (&cr_entry->credential[1], + credentials[i].issuer_attribute, + credentials[i].issuer_attribute_len); + 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, @@ -820,22 +1098,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. * @@ -847,7 +1160,7 @@ client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); } @@ -865,7 +1178,7 @@ client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client); return client; @@ -890,6 +1203,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); @@ -910,6 +1229,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 */