From de8925d37dfdd77bba3a1cfe550ddd449a196b78 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Tue, 4 Feb 2020 21:15:59 +0100 Subject: [PATCH] add attestation API --- src/include/gnunet_protocols.h | 17 +- src/include/gnunet_reclaim_service.h | 72 ++++- src/reclaim/gnunet-reclaim.c | 3 +- src/reclaim/gnunet-service-reclaim.c | 337 ++++++++++++++++++----- src/reclaim/plugin_rest_openid_connect.c | 85 ++++-- src/reclaim/plugin_rest_reclaim.c | 91 ++---- src/reclaim/reclaim.h | 58 ++-- src/reclaim/reclaim_api.c | 139 +++++++++- 8 files changed, 603 insertions(+), 199 deletions(-) diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 8091fb367..d92015787 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -2720,21 +2720,26 @@ extern "C" { #define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT 979 -#define GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_STORE 980 +#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_START 963 + +#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP 964 + +#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT 965 + /************************************************** * * ABD MESSAGE TYPES */ -#define GNUNET_MESSAGE_TYPE_ABD_VERIFY 981 +#define GNUNET_MESSAGE_TYPE_ABD_VERIFY 991 -#define GNUNET_MESSAGE_TYPE_ABD_VERIFY_RESULT 982 +#define GNUNET_MESSAGE_TYPE_ABD_VERIFY_RESULT 992 -#define GNUNET_MESSAGE_TYPE_ABD_COLLECT 983 +#define GNUNET_MESSAGE_TYPE_ABD_COLLECT 993 -#define GNUNET_MESSAGE_TYPE_ABD_COLLECT_RESULT 984 +#define GNUNET_MESSAGE_TYPE_ABD_COLLECT_RESULT 994 -#define GNUNET_MESSAGE_TYPE_ABD_INTERMEDIATE_RESULT 985 +#define GNUNET_MESSAGE_TYPE_ABD_INTERMEDIATE_RESULT 995 /******************************************************************************/ diff --git a/src/include/gnunet_reclaim_service.h b/src/include/gnunet_reclaim_service.h index 4ead87003..c9c4fa5d1 100644 --- a/src/include/gnunet_reclaim_service.h +++ b/src/include/gnunet_reclaim_service.h @@ -107,7 +107,6 @@ typedef void (*GNUNET_RECLAIM_ContinuationWithStatus) (void *cls, int32_t success, const char *emsg); - /** * Callback used to notify the client of attribute results. * @@ -117,6 +116,18 @@ typedef void (*GNUNET_RECLAIM_ContinuationWithStatus) (void *cls, * @param attestation The attestation for the attribute (may be NULL) */ typedef void (*GNUNET_RECLAIM_AttributeResult) ( + void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, + const struct GNUNET_RECLAIM_Attribute *attr); + +/** + * Callback used to notify the client of attribute results. + * + * @param cls The callback closure + * @param identity The identity authoritative over the attributes + * @param attr The attribute + * @param attestation The attestation for the attribute (may be NULL) + */ +typedef void (*GNUNET_RECLAIM_AttributeTicketResult) ( void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr, const struct GNUNET_RECLAIM_Attestation *attestation); @@ -280,6 +291,63 @@ GNUNET_RECLAIM_get_attributes_stop ( struct GNUNET_RECLAIM_AttributeIterator *it); +/** + * List all attestations for a local identity. + * This MUST lock the `struct GNUNET_RECLAIM_Handle` + * for any other calls than #GNUNET_RECLAIM_get_attestations_next() and + * #GNUNET_RECLAIM_get_attestations_stop. @a proc will be called once + * immediately, and then again after + * #GNUNET_RECLAIM_get_attestations_next() is invoked. + * + * On error (disconnect), @a error_cb will be invoked. + * On normal completion, @a finish_cb proc will be + * invoked. + * + * @param h Handle to the re:claimID service + * @param identity Identity to iterate over + * @param error_cb Function to call on error (i.e. disconnect), + * the handle is afterwards invalid + * @param error_cb_cls Closure for @a error_cb + * @param proc Function to call on each attestation + * @param proc_cls Closure for @a proc + * @param finish_cb Function to call on completion + * the handle is afterwards invalid + * @param finish_cb_cls Closure for @a finish_cb + * @return an iterator Handle to use for iteration + */ +struct GNUNET_RECLAIM_AttestationIterator * +GNUNET_RECLAIM_get_attestations_start ( + struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, + GNUNET_SCHEDULER_TaskCallback error_cb, + void *error_cb_cls, + GNUNET_RECLAIM_AttestationResult proc, + void *proc_cls, + GNUNET_SCHEDULER_TaskCallback finish_cb, + void *finish_cb_cls); + + +/** + * Calls the record processor specified in #GNUNET_RECLAIM_get_attestation_start + * for the next record. + * + * @param it the iterator + */ +void +GNUNET_RECLAIM_get_attestations_next (struct GNUNET_RECLAIM_AttestationIterator *ait); + + +/** + * Stops iteration and releases the handle for further calls. Must + * be called on any iteration that has not yet completed prior to calling + * #GNUNET_RECLAIM_disconnect. + * + * @param it the iterator + */ +void +GNUNET_RECLAIM_get_attestations_stop (struct GNUNET_RECLAIM_AttestationIterator *ait); + + /** * Issues a ticket to a relying party. The identity may use * GNUNET_RECLAIM_ticket_consume to consume the ticket @@ -340,7 +408,7 @@ GNUNET_RECLAIM_ticket_consume ( struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, const struct GNUNET_RECLAIM_Ticket *ticket, - GNUNET_RECLAIM_AttributeResult cb, void *cb_cls); + GNUNET_RECLAIM_AttributeTicketResult cb, void *cb_cls); /** diff --git a/src/reclaim/gnunet-reclaim.c b/src/reclaim/gnunet-reclaim.c index b72336907..93d9ee3df 100644 --- a/src/reclaim/gnunet-reclaim.c +++ b/src/reclaim/gnunet-reclaim.c @@ -447,8 +447,7 @@ iter_finished (void *cls) static void iter_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, - const struct GNUNET_RECLAIM_Attribute *attr, - const struct GNUNET_RECLAIM_Attestation *attest) + const struct GNUNET_RECLAIM_Attribute *attr) { struct GNUNET_RECLAIM_AttributeListEntry *le; char *attrs_tmp; diff --git a/src/reclaim/gnunet-service-reclaim.c b/src/reclaim/gnunet-service-reclaim.c index 15f9a8385..f6fd04eeb 100644 --- a/src/reclaim/gnunet-service-reclaim.c +++ b/src/reclaim/gnunet-service-reclaim.c @@ -90,17 +90,17 @@ struct TicketIteration /** * An attribute iteration operation. */ -struct AttributeIterator +struct Iterator { /** * Next element in the DLL */ - struct AttributeIterator *next; + struct Iterator *next; /** * Previous element in the DLL */ - struct AttributeIterator *prev; + struct Iterator *prev; /** * IDP client which intiated this zone iteration @@ -121,6 +121,11 @@ struct AttributeIterator * The operation id fot the zone iteration in the response for the client */ uint32_t request_id; + + /** + * Context + */ + void *ctx; }; @@ -154,14 +159,28 @@ struct IdpClient * Attribute iteration operations in * progress initiated by this client */ - struct AttributeIterator *attr_iter_head; + struct Iterator *attr_iter_head; + + /** + * Tail of the DLL of + * Attribute iteration operations + * in progress initiated by this client + */ + struct Iterator *attr_iter_tail; + + /** + * Head of the DLL of + * Attribute iteration operations in + * progress initiated by this client + */ + struct Iterator *attest_iter_head; /** * Tail of the DLL of * Attribute iteration operations * in progress initiated by this client */ - struct AttributeIterator *attr_iter_tail; + struct Iterator *attest_iter_tail; /** * Head of DLL of ticket iteration ops @@ -512,7 +531,7 @@ cleanup_as_handle (struct AttributeStoreHandle *ash) static void cleanup_client (struct IdpClient *idp) { - struct AttributeIterator *ai; + struct Iterator *ai; struct TicketIteration *ti; struct TicketRevocationOperation *rop; struct TicketIssueOperation *iss; @@ -550,6 +569,13 @@ cleanup_client (struct IdpClient *idp) GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai); GNUNET_free (ai); } + while (NULL != (ai = idp->attest_iter_head)) + { + GNUNET_CONTAINER_DLL_remove (idp->attest_iter_head, idp->attest_iter_tail, + ai); + GNUNET_free (ai); + } + while (NULL != (rop = idp->revoke_op_head)) { GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, idp->revoke_op_tail, rop); @@ -1641,7 +1667,7 @@ handle_attestation_delete_message (void *cls, static void attr_iter_finished (void *cls) { - struct AttributeIterator *ai = cls; + struct Iterator *ai = cls; struct GNUNET_MQ_Envelope *env; struct AttributeResultMessage *arm; @@ -1665,7 +1691,7 @@ attr_iter_finished (void *cls) static void attr_iter_error (void *cls) { - struct AttributeIterator *ai = cls; + struct Iterator *ai = cls; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n"); attr_iter_finished (ai); @@ -1688,7 +1714,7 @@ attr_iter_cb (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { - struct AttributeIterator *ai = cls; + struct Iterator *ai = cls; struct GNUNET_MQ_Envelope *env; char *data_tmp; @@ -1697,71 +1723,25 @@ attr_iter_cb (void *cls, GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1); return; } - if (rd_count > 1) - { - if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[0].record_type) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Found Ticket. Ignoring.\n"); - GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1); - return; - } - else if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION != rd[0].record_type) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Non-Attestation record with multiple entries found: %u\n", - rd[0].record_type); - GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1); - return; - } - } for (int i = 0; ins_it, 1); - return; - } - // FIXME Send attribute TOGETHER with respective attestation if applicable - if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE == rd[i].record_type) - { - struct AttributeResultMessage *arm; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n", - label); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending ATTRIBUTE_RESULT message\n"); - env = GNUNET_MQ_msg_extra (arm, - rd[i].data_size, - GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT); - arm->id = htonl (ai->request_id); - arm->attr_len = htons (rd[i].data_size); - GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity); - data_tmp = (char *) &arm[1]; - GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size); - GNUNET_MQ_send (ai->client->mq, env); - } - else - { - if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION == rd[i].record_type) - { - struct AttributeResultMessage *arm; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attestation under: %s\n", - label); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending ATTESTATION_RESULT message\n"); - env = GNUNET_MQ_msg_extra (arm, - rd[i].data_size, - GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT); - arm->id = htonl (ai->request_id); - arm->attr_len = htons (rd[i].data_size); - GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity); - data_tmp = (char *) &arm[1]; - GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size); - GNUNET_MQ_send (ai->client->mq, env); - } - } + if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd[i].record_type) + continue; + struct AttributeResultMessage *arm; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n", + label); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending ATTRIBUTE_RESULT message\n"); + env = GNUNET_MQ_msg_extra (arm, + rd[i].data_size, + GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT); + arm->id = htonl (ai->request_id); + arm->attr_len = htons (rd[i].data_size); + GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity); + data_tmp = (char *) &arm[1]; + GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size); + GNUNET_MQ_send (ai->client->mq, env); } } @@ -1777,11 +1757,11 @@ handle_iteration_start (void *cls, const struct AttributeIterationStartMessage *ais_msg) { struct IdpClient *idp = cls; - struct AttributeIterator *ai; + struct Iterator *ai; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_ITERATION_START message\n"); - ai = GNUNET_new (struct AttributeIterator); + ai = GNUNET_new (struct Iterator); ai->request_id = ntohl (ais_msg->id); ai->client = idp; ai->identity = ais_msg->identity; @@ -1810,7 +1790,7 @@ handle_iteration_stop (void *cls, const struct AttributeIterationStopMessage *ais_msg) { struct IdpClient *idp = cls; - struct AttributeIterator *ai; + struct Iterator *ai; uint32_t rid; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -1843,7 +1823,7 @@ handle_iteration_next (void *cls, const struct AttributeIterationNextMessage *ais_msg) { struct IdpClient *idp = cls; - struct AttributeIterator *ai; + struct Iterator *ai; uint32_t rid; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -1863,6 +1843,200 @@ handle_iteration_next (void *cls, } +/************************************************* +* Attestation iteration +*************************************************/ + + +/** + * Done iterating over attestations + * + * @param cls our iterator handle + */ +static void +attest_iter_finished (void *cls) +{ + struct Iterator *ai = cls; + struct GNUNET_MQ_Envelope *env; + struct AttestationResultMessage *arm; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTESTATION_RESULT message\n"); + env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT); + arm->id = htonl (ai->request_id); + arm->attestation_len = htons (0); + GNUNET_MQ_send (ai->client->mq, env); + GNUNET_CONTAINER_DLL_remove (ai->client->attest_iter_head, + ai->client->attest_iter_tail, + ai); + GNUNET_free (ai); +} + + +/** + * Error iterating over attestations. Abort. + * + * @param cls our attribute iteration handle + */ +static void +attest_iter_error (void *cls) +{ + struct Iterator *ai = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attestations\n"); + attest_iter_finished (ai); +} + + +/** + * Got record. Return attestation. + * + * @param cls our attribute iterator + * @param zone zone we are iterating + * @param label label of the records + * @param rd_count record count + * @param rd records + */ +static void +attest_iter_cb (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct Iterator *ai = cls; + struct GNUNET_MQ_Envelope *env; + char *data_tmp; + + if (rd_count == 0) + { + GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1); + return; + } + + for (int i = 0; iid = htonl (ai->request_id); + arm->attestation_len = htons (rd[i].data_size); + GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity); + data_tmp = (char *) &arm[1]; + GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size); + GNUNET_MQ_send (ai->client->mq, env); + } +} + + +/** + * Iterate over zone to get attributes + * + * @param cls our client + * @param ais_msg the iteration message to start + */ +static void +handle_attestation_iteration_start (void *cls, + const struct + AttestationIterationStartMessage *ais_msg) +{ + struct IdpClient *idp = cls; + struct Iterator *ai; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received ATTESTATION_ITERATION_START message\n"); + ai = GNUNET_new (struct Iterator); + ai->request_id = ntohl (ais_msg->id); + ai->client = idp; + ai->identity = ais_msg->identity; + + GNUNET_CONTAINER_DLL_insert (idp->attest_iter_head, idp->attest_iter_tail, + ai); + ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh, + &ai->identity, + &attest_iter_error, + ai, + &attest_iter_cb, + ai, + &attest_iter_finished, + ai); + GNUNET_SERVICE_client_continue (idp->client); +} + + +/** + * Handle iteration stop message from client + * + * @param cls the client + * @param ais_msg the stop message + */ +static void +handle_attestation_iteration_stop (void *cls, + const struct + AttestationIterationStopMessage *ais_msg) +{ + struct IdpClient *idp = cls; + struct Iterator *ai; + uint32_t rid; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s' message\n", + "ATTESTATION_ITERATION_STOP"); + rid = ntohl (ais_msg->id); + for (ai = idp->attest_iter_head; NULL != ai; ai = ai->next) + if (ai->request_id == rid) + break; + if (NULL == ai) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (idp->client); + return; + } + GNUNET_CONTAINER_DLL_remove (idp->attest_iter_head, idp->attest_iter_tail, + ai); + GNUNET_free (ai); + GNUNET_SERVICE_client_continue (idp->client); +} + + +/** + * Client requests next attestation from iterator + * + * @param cls the client + * @param ais_msg the message + */ +static void +handle_attestation_iteration_next (void *cls, + const struct + AttestationIterationNextMessage *ais_msg) +{ + struct IdpClient *idp = cls; + struct Iterator *ai; + uint32_t rid; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received ATTESTATION_ITERATION_NEXT message\n"); + rid = ntohl (ais_msg->id); + for (ai = idp->attest_iter_head; NULL != ai; ai = ai->next) + if (ai->request_id == rid) + break; + if (NULL == ai) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (idp->client); + return; + } + GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1); + GNUNET_SERVICE_client_continue (idp->client); +} + + /****************************************************** * Ticket iteration ******************************************************/ @@ -2115,6 +2289,19 @@ GNUNET_SERVICE_MAIN ( GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP, struct AttributeIterationStopMessage, NULL), + GNUNET_MQ_hd_fixed_size (attestation_iteration_start, + GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_START, + struct AttestationIterationStartMessage, + NULL), + GNUNET_MQ_hd_fixed_size (attestation_iteration_next, + GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT, + struct AttestationIterationNextMessage, + NULL), + GNUNET_MQ_hd_fixed_size (attestation_iteration_stop, + GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP, + struct AttestationIterationStopMessage, + NULL), + GNUNET_MQ_hd_var_size (issue_ticket_message, GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET, struct IssueTicketMessage, diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 610f93dbe..345dbeed6 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -456,6 +456,12 @@ struct RequestHandle */ struct GNUNET_RECLAIM_AttributeIterator *attr_it; + /** + * Attestation iterator + */ + struct GNUNET_RECLAIM_AttestationIterator *attest_it; + + /** * Ticket iterator */ @@ -529,7 +535,6 @@ struct RequestHandle static void cleanup_handle (struct RequestHandle *handle) { - struct GNUNET_RECLAIM_AttributeListEntry *claim_entry; struct EgoEntry *ego_entry; struct EgoEntry *ego_tmp; @@ -540,6 +545,8 @@ cleanup_handle (struct RequestHandle *handle) GNUNET_IDENTITY_disconnect (handle->identity_handle); if (NULL != handle->attr_it) GNUNET_RECLAIM_get_attributes_stop (handle->attr_it); + if (NULL != handle->attest_it) + GNUNET_RECLAIM_get_attestations_stop (handle->attest_it); if (NULL != handle->ticket_it) GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it); if (NULL != handle->idp) @@ -961,7 +968,53 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket) static void -oidc_collect_finished_cb (void *cls) +oidc_attest_collect_finished_cb (void *cls) +{ + struct RequestHandle *handle = cls; + + handle->attest_it = NULL; + handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp, + &handle->priv_key, + &handle->oidc->client_pkey, + handle->attr_list, + &oidc_ticket_issue_cb, + handle); +} + + +/** + * Collects all attributes for an ego if in scope parameter + */ +static void +oidc_attest_collect (void *cls, + const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, + const struct GNUNET_RECLAIM_Attestation *attest) +{ + struct RequestHandle *handle = cls; + struct GNUNET_RECLAIM_AttributeListEntry *le; + + for (le = handle->attr_list->list_head; NULL != le; le = le->next) + { + if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&le->attribute->attestation, + &attest->id)) + { + struct GNUNET_RECLAIM_AttestationListEntry *ale; + ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry); + ale->attestation = GNUNET_RECLAIM_attestation_new (attest->name, + attest->type, + attest->data, + attest->data_size); + GNUNET_CONTAINER_DLL_insert (handle->attests_list->list_head, + handle->attests_list->list_tail, + ale); + } + } + GNUNET_RECLAIM_get_attestations_next (handle->attest_it); +} + + +static void +oidc_attr_collect_finished_cb (void *cls) { struct RequestHandle *handle = cls; @@ -974,6 +1027,17 @@ oidc_collect_finished_cb (void *cls) GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); return; } + handle->attests_list = GNUNET_new (struct GNUNET_RECLAIM_AttestationList); + handle->attest_it = + GNUNET_RECLAIM_get_attestations_start (handle->idp, + &handle->priv_key, + &oidc_iteration_error, + handle, + &oidc_attest_collect, + handle, + &oidc_attest_collect_finished_cb, + handle); + handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp, &handle->priv_key, &handle->oidc->client_pkey, @@ -989,8 +1053,7 @@ oidc_collect_finished_cb (void *cls) static void oidc_attr_collect (void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, - const struct GNUNET_RECLAIM_Attribute *attr, - const struct GNUNET_RECLAIM_Attestation *attest) + const struct GNUNET_RECLAIM_Attribute *attr) { struct RequestHandle *handle = cls; struct GNUNET_RECLAIM_AttributeListEntry *le; @@ -1026,18 +1089,6 @@ oidc_attr_collect (void *cls, GNUNET_CONTAINER_DLL_insert (handle->attr_list->list_head, handle->attr_list->list_tail, le); - if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&attr->attestation)) - { - struct GNUNET_RECLAIM_AttestationListEntry *ale; - ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry); - ale->attestation = GNUNET_RECLAIM_attestation_new (attest->name, - attest->type, - attest->data, - attest->data_size); - GNUNET_CONTAINER_DLL_insert (handle->attests_list->list_head, - handle->attests_list->list_tail, - ale); - } GNUNET_RECLAIM_get_attributes_next (handle->attr_it); } @@ -1104,7 +1155,7 @@ code_redirect (void *cls) handle, &oidc_attr_collect, handle, - &oidc_collect_finished_cb, + &oidc_attr_collect_finished_cb, handle); return; } diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c index fcb34e11a..6f7a5987b 100644 --- a/src/reclaim/plugin_rest_reclaim.c +++ b/src/reclaim/plugin_rest_reclaim.c @@ -712,13 +712,14 @@ list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle, priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); handle->idp = GNUNET_RECLAIM_connect (cfg); handle->attest_it = GNUNET_RECLAIM_get_attestations_start (handle->idp, - priv_key, - &collect_error_cb, - handle, - &attest_collect, - handle, - &collect_finished_cb, - handle); + priv_key, + &collect_error_cb, + handle, + &attest_collect, + handle, + & + collect_finished_cb, + handle); } @@ -1000,67 +1001,33 @@ parse_jwt (const struct GNUNET_RECLAIM_Attestation *attest, static void attr_collect (void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, - const struct GNUNET_RECLAIM_Attribute *attr, - const struct GNUNET_RECLAIM_Attestation *attest) + const struct GNUNET_RECLAIM_Attribute *attr) { struct RequestHandle *handle = cls; json_t *attr_obj; const char *type; char *id_str; - if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&attr->attestation)) - { - struct GNUNET_RECLAIM_Attribute *attr2; - attr2 = parse_jwt (attest, attr->data); - if (NULL == attr2) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Attribute Collection with unparsed Attestation\n"); - return; - } - attr2->name = attr->name; - char *tmp_value; - tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr2->type, - attr2->data, - attr2->data_size); - attr_obj = json_object (); - json_object_set_new (attr_obj, "value", json_string (tmp_value)); - json_object_set_new (attr_obj, "name", json_string (attr2->name)); - json_object_set_new (attr_obj, "flag", json_string ("1")); - type = GNUNET_RECLAIM_attribute_number_to_typename (attr2->type); - json_object_set_new (attr_obj, "type", json_string (type)); - id_str = GNUNET_STRINGS_data_to_string_alloc (&attr2->id, - sizeof(attr2->id)); - json_object_set_new (attr_obj, "id", json_string (id_str)); - json_array_append (handle->resp_object, attr_obj); - json_decref (attr_obj); - GNUNET_free (tmp_value); - } - else - { - char *tmp_value; - char *flag_str; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name); - - tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr->type, - attr->data, - attr->data_size); - - attr_obj = json_object (); - json_object_set_new (attr_obj, "value", json_string (tmp_value)); - json_object_set_new (attr_obj, "name", json_string (attr->name)); - GNUNET_asprintf (&flag_str,"%d",attr->flag); - json_object_set_new (attr_obj, "flag", json_string (flag_str)); - type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type); - json_object_set_new (attr_obj, "type", json_string (type)); - id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id, - sizeof(attr->id)); - json_object_set_new (attr_obj, "id", json_string (id_str)); - json_array_append (handle->resp_object, attr_obj); - json_decref (attr_obj); - GNUNET_free (tmp_value); - GNUNET_RECLAIM_get_attributes_next (handle->attr_it); - } + char *tmp_value; + tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr->type, + attr->data, + attr->data_size); + attr_obj = json_object (); + json_object_set_new (attr_obj, "value", json_string (tmp_value)); + json_object_set_new (attr_obj, "name", json_string (attr->name)); + + json_object_set_new (attr_obj, "flag", json_string ("1")); + type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type); + json_object_set_new (attr_obj, "type", json_string (type)); + id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id, + sizeof(attr->id)); + json_object_set_new (attr_obj, "id", json_string (id_str)); + id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->attestation, + sizeof(attr->attestation)); + json_object_set_new (attr_obj, "attestation", json_string (id_str)); + json_array_append (handle->resp_object, attr_obj); + json_decref (attr_obj); + GNUNET_free (tmp_value); } diff --git a/src/reclaim/reclaim.h b/src/reclaim/reclaim.h index 3da49fe7a..7b5d7ab19 100644 --- a/src/reclaim/reclaim.h +++ b/src/reclaim/reclaim.h @@ -195,12 +195,12 @@ struct AttestationResultMessage /** - * Reference plus Attestation is returned from the idp. + * Start a attribute iteration for the given identity */ -struct ReferenceResultMessage +struct AttributeIterationStartMessage { /** - * Message header + * Message */ struct GNUNET_MessageHeader header; @@ -210,34 +210,33 @@ struct ReferenceResultMessage uint32_t id GNUNET_PACKED; /** - * Length of serialized attestation data + * Identity. */ - uint16_t attest_len GNUNET_PACKED; + struct GNUNET_CRYPTO_EcdsaPrivateKey identity; +}; - /** - * Length of serialized reference data - */ - uint16_t ref_len GNUNET_PACKED; +/** + * Ask for next result of attribute iteration for the given operation + */ +struct AttributeIterationNextMessage +{ /** - * always zero (for alignment) + * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT */ - uint16_t reserved GNUNET_PACKED; + struct GNUNET_MessageHeader header; /** - * The public key of the identity. - */ - struct GNUNET_CRYPTO_EcdsaPublicKey identity; - - /* followed by: - * serialized reference data + attestation data + * Unique identifier for this request (for key collisions). */ + uint32_t id GNUNET_PACKED; }; + /** - * Start a attribute iteration for the given identity + * Start a attestation iteration for the given identity */ -struct AttributeIterationStartMessage +struct AttestationIterationStartMessage { /** * Message @@ -257,9 +256,9 @@ struct AttributeIterationStartMessage /** - * Ask for next result of attribute iteration for the given operation + * Ask for next result of attestation iteration for the given operation */ -struct AttributeIterationNextMessage +struct AttestationIterationNextMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT @@ -273,6 +272,23 @@ struct AttributeIterationNextMessage }; +/** + * Stop attestation iteration for the given operation + */ +struct AttestationIterationStopMessage +{ + /** + * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP + */ + struct GNUNET_MessageHeader header; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; +}; + + /** * Stop attribute iteration for the given operation */ diff --git a/src/reclaim/reclaim_api.c b/src/reclaim/reclaim_api.c index 0fcf95ee3..89b9ea0f7 100644 --- a/src/reclaim/reclaim_api.c +++ b/src/reclaim/reclaim_api.c @@ -71,6 +71,11 @@ struct GNUNET_RECLAIM_Operation */ GNUNET_RECLAIM_AttributeResult ar_cb; + /** + * Attribute result callback + */ + GNUNET_RECLAIM_AttributeTicketResult atr_cb; + /** * Attestation result callback */ @@ -607,11 +612,11 @@ handle_consume_ticket_result (void *cls, read_ptr = ((char *) &msg[1]) + attrs_len; attests = GNUNET_RECLAIM_attestation_list_deserialize (read_ptr, attests_len); - if (NULL != op->ar_cb) + if (NULL != op->atr_cb) { if (NULL == attrs) { - op->ar_cb (op->cls, &msg->identity, NULL, NULL); + op->atr_cb (op->cls, &msg->identity, NULL, NULL); } else { @@ -626,7 +631,7 @@ handle_consume_ticket_result (void *cls, GNUNET_RECLAIM_id_is_equal (&le->attribute->id, &ale->attestation->id)) { - op->ar_cb (op->cls, &msg->identity, + op->atr_cb (op->cls, &msg->identity, le->attribute, ale->attestation); break; } @@ -635,7 +640,7 @@ handle_consume_ticket_result (void *cls, } else // No attestations { - op->ar_cb (op->cls, &msg->identity, + op->atr_cb (op->cls, &msg->identity, le->attribute, NULL); } } @@ -644,7 +649,7 @@ handle_consume_ticket_result (void *cls, attrs = NULL; attests = NULL; } - op->ar_cb (op->cls, NULL, NULL, NULL); + op->atr_cb (op->cls, NULL, NULL, NULL); } GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); free_op (op); @@ -730,7 +735,7 @@ handle_attribute_result (void *cls, const struct AttributeResultMessage *msg) if (NULL != op) { if (NULL != op->ar_cb) - op->ar_cb (op->cls, NULL, NULL, NULL); + op->ar_cb (op->cls, NULL, NULL); GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); free_op (op); } @@ -739,20 +744,16 @@ handle_attribute_result (void *cls, const struct AttributeResultMessage *msg) { struct GNUNET_RECLAIM_Attribute *attr; - struct GNUNET_RECLAIM_Attestation *attest; - char *read_ptr; attr = GNUNET_RECLAIM_attribute_deserialize ((char *) &msg[1], attr_len); - read_ptr = ((char *) &msg[1]) + attr_len; - attest = GNUNET_RECLAIM_attestation_deserialize (read_ptr, attest_len); if (NULL != it) { if (NULL != it->proc) - it->proc (it->proc_cls, &msg->identity, attr, attest); + it->proc (it->proc_cls, &msg->identity, attr); } else if (NULL != op) { if (NULL != op->ar_cb) - op->ar_cb (op->cls, &msg->identity, attr, attest); + op->ar_cb (op->cls, &msg->identity, attr); } GNUNET_free (attr); return; @@ -1369,6 +1370,116 @@ GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it) } +/** + * List all attestations for a local identity. + * This MUST lock the `struct GNUNET_RECLAIM_Handle` + * for any other calls than #GNUNET_RECLAIM_get_attestations_next() and + * #GNUNET_RECLAIM_get_attestations_stop. @a proc will be called once + * immediately, and then again after + * #GNUNET_RECLAIM_get_attestations_next() is invoked. + * + * On error (disconnect), @a error_cb will be invoked. + * On normal completion, @a finish_cb proc will be + * invoked. + * + * @param h Handle to the re:claimID service + * @param identity Identity to iterate over + * @param error_cb Function to call on error (i.e. disconnect), + * the handle is afterwards invalid + * @param error_cb_cls Closure for @a error_cb + * @param proc Function to call on each attestation + * @param proc_cls Closure for @a proc + * @param finish_cb Function to call on completion + * the handle is afterwards invalid + * @param finish_cb_cls Closure for @a finish_cb + * @return an iterator Handle to use for iteration + */ +struct GNUNET_RECLAIM_AttestationIterator * +GNUNET_RECLAIM_get_attestations_start ( + struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, + GNUNET_SCHEDULER_TaskCallback error_cb, + void *error_cb_cls, + GNUNET_RECLAIM_AttestationResult proc, + void *proc_cls, + GNUNET_SCHEDULER_TaskCallback finish_cb, + void *finish_cb_cls) +{ + struct GNUNET_RECLAIM_AttestationIterator *ait; + struct GNUNET_MQ_Envelope *env; + struct AttestationIterationStartMessage *msg; + uint32_t rid; + + rid = h->r_id_gen++; + ait = GNUNET_new (struct GNUNET_RECLAIM_AttestationIterator); + ait->h = h; + ait->error_cb = error_cb; + ait->error_cb_cls = error_cb_cls; + ait->finish_cb = finish_cb; + ait->finish_cb_cls = finish_cb_cls; + ait->proc = proc; + ait->proc_cls = proc_cls; + ait->r_id = rid; + ait->identity = *identity; + GNUNET_CONTAINER_DLL_insert_tail (h->ait_head, h->ait_tail, ait); + env = + GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START); + msg->id = htonl (rid); + msg->identity = *identity; + if (NULL == h->mq) + ait->env = env; + else + GNUNET_MQ_send (h->mq, env); + return ait; +} + + +/** + * Calls the record processor specified in #GNUNET_RECLAIM_get_attestation_start + * for the next record. + * + * @param it the iterator + */ +void +GNUNET_RECLAIM_get_attestations_next (struct GNUNET_RECLAIM_AttestationIterator *ait) +{ + struct GNUNET_RECLAIM_Handle *h = ait->h; + struct AttestationIterationNextMessage *msg; + struct GNUNET_MQ_Envelope *env; + + env = + GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT); + msg->id = htonl (ait->r_id); + GNUNET_MQ_send (h->mq, env); +} + + +/** + * Stops iteration and releases the handle for further calls. Must + * be called on any iteration that has not yet completed prior to calling + * #GNUNET_RECLAIM_disconnect. + * + * @param it the iterator + */ +void +GNUNET_RECLAIM_get_attestations_stop (struct GNUNET_RECLAIM_AttestationIterator *ait) +{ + struct GNUNET_RECLAIM_Handle *h = ait->h; + struct GNUNET_MQ_Envelope *env; + struct AttestationIterationStopMessage *msg; + + if (NULL != h->mq) + { + env = + GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP); + msg->id = htonl (ait->r_id); + GNUNET_MQ_send (h->mq, env); + } + free_ait (ait); +} + + + /** * Issues a ticket to another relying party. The identity may use * @GNUNET_RECLAIM_ticket_consume to consume the ticket @@ -1436,7 +1547,7 @@ GNUNET_RECLAIM_ticket_consume ( struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, const struct GNUNET_RECLAIM_Ticket *ticket, - GNUNET_RECLAIM_AttributeResult cb, + GNUNET_RECLAIM_AttributeTicketResult cb, void *cb_cls) { struct GNUNET_RECLAIM_Operation *op; @@ -1444,7 +1555,7 @@ GNUNET_RECLAIM_ticket_consume ( op = GNUNET_new (struct GNUNET_RECLAIM_Operation); op->h = h; - op->ar_cb = cb; + op->atr_cb = cb; op->cls = cb_cls; op->r_id = h->r_id_gen++; GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op); -- 2.25.1