From 43f611f70255ed17106bdf16b29a04b1c6c1c43e Mon Sep 17 00:00:00 2001 From: Markus Voggenreiter Date: Sun, 13 Oct 2019 16:31:17 +0200 Subject: [PATCH] Add Attestations via Reclaim Service --- src/include/gnunet_protocols.h | 2 + src/include/gnunet_reclaim_service.h | 22 ++ src/reclaim/gnunet-service-reclaim.c | 144 +++++++++++ src/reclaim/plugin_rest_reclaim.c | 342 +-------------------------- src/reclaim/reclaim_api.c | 46 ++++ 5 files changed, 225 insertions(+), 331 deletions(-) diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index cd7cb50de..8de779ad3 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -2714,6 +2714,8 @@ extern "C" { #define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE 976 +#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE 977 + /************************************************** * * ABD MESSAGE TYPES diff --git a/src/include/gnunet_reclaim_service.h b/src/include/gnunet_reclaim_service.h index 237d791d9..a9061d6e8 100644 --- a/src/include/gnunet_reclaim_service.h +++ b/src/include/gnunet_reclaim_service.h @@ -151,6 +151,28 @@ GNUNET_RECLAIM_attribute_store ( GNUNET_RECLAIM_ContinuationWithStatus cont, void *cont_cls); +/** + * Store an attestation. If the attestation is already present, + * it is replaced with the new attestation. + * + * @param h handle to the re:claimID service + * @param pkey private key of the identity + * @param attr the attestation value + * @param exp_interval the relative expiration interval for the attestation + * @param cont continuation to call when done + * @param cont_cls closure for @a cont + * @return handle to abort the request + */ +struct GNUNET_RECLAIM_Operation * +GNUNET_RECLAIM_attestation_store ( + struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, + const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr, + const struct GNUNET_TIME_Relative *exp_interval, + GNUNET_RECLAIM_ContinuationWithStatus cont, + void *cont_cls); + + /** * Delete an attribute. Tickets used to share this attribute are updated * accordingly. diff --git a/src/reclaim/gnunet-service-reclaim.c b/src/reclaim/gnunet-service-reclaim.c index a83ea05a6..d6c93812f 100644 --- a/src/reclaim/gnunet-service-reclaim.c +++ b/src/reclaim/gnunet-service-reclaim.c @@ -327,6 +327,11 @@ struct AttributeStoreHandle */ struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim; + /** + * The attestation to store + */ + struct GNUNET_RECLAIM_ATTESTATION_Claim *attest; + /** * The attribute expiration interval */ @@ -486,6 +491,8 @@ cleanup_as_handle (struct AttributeStoreHandle *ash) GNUNET_NAMESTORE_cancel (ash->ns_qe); if (NULL != ash->claim) GNUNET_free (ash->claim); + if (NULL != ash->attest) + GNUNET_free (ash->attest); GNUNET_free (ash); } @@ -1022,6 +1029,139 @@ handle_attribute_store_message (void *cls, } +/** + * Attestation store result handler + * + * @param cls our attribute store handle + * @param success GNUNET_OK if successful + * @param emsg error message (NULL if success=GNUNET_OK) + */ +static void +attest_store_cont (void *cls, int32_t success, const char *emsg) +{ + struct AttributeStoreHandle *ash = cls; + struct GNUNET_MQ_Envelope *env; + struct SuccessResultMessage *acr_msg; + + ash->ns_qe = NULL; + GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head, + ash->client->store_op_tail, + ash); + + if (GNUNET_SYSERR == success) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to store attestation %s\n", + emsg); + cleanup_as_handle (ash); + GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); + return; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n"); + env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE); + acr_msg->id = htonl (ash->r_id); + acr_msg->op_result = htonl (GNUNET_OK); + GNUNET_MQ_send (ash->client->mq, env); + cleanup_as_handle (ash); +} + +/** + * Add a new attestation + * + * @param cls the AttributeStoreHandle + */ +static void +attest_store_task (void *cls) +{ + struct AttributeStoreHandle *ash = cls; + struct GNUNET_GNSRECORD_Data rd[1]; + char *buf; + char *label; + size_t buf_size; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attestation\n"); + buf_size = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (ash->attest); + buf = GNUNET_malloc (buf_size); + // Give the ash a new id if unset + if (0 == ash->attest->id) + ash->attest->id + = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX); + GNUNET_RECLAIM_ATTESTATION_serialize (ash->attest, buf); + label = GNUNET_STRINGS_data_to_string_alloc (&ash->attest->id, + sizeof(uint64_t)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label); + + rd[0].data_size = buf_size; + rd[0].data = buf; + rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR; + rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; + rd[0].expiration_time = ash->exp.rel_value_us; + ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh, + &ash->identity, + label, + 1, + rd, + &attest_store_cont, + ash); + GNUNET_free (buf); + GNUNET_free (label); +} + +/** + * Check an attestation store message + * + * @param cls unused + * @param sam the message to check + */ +static int +check_attestation_store_message (void *cls, + const struct AttributeStoreMessage *sam) +{ + uint16_t size; + + size = ntohs (sam->header.size); + if (size <= sizeof(struct AttributeStoreMessage)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + +/** +* Handle an attestation store message +* +* @param cls our client +* @param sam the message to handle +*/ +static void +handle_attestation_store_message (void *cls, + const struct AttributeStoreMessage *sam) +{ + struct AttributeStoreHandle *ash; + struct IdpClient *idp = cls; + size_t data_len; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_STORE message\n"); + + data_len = ntohs (sam->attr_len); + + ash = GNUNET_new (struct AttributeStoreHandle); + ash->attest = GNUNET_RECLAIM_ATTESTATION_deserialize ((char *) &sam[1], + data_len); + + ash->r_id = ntohl (sam->id); + ash->identity = sam->identity; + ash->exp.rel_value_us = GNUNET_ntohll (sam->exp); + GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey); + + GNUNET_SERVICE_client_continue (idp->client); + ash->client = idp; + GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash); + GNUNET_SCHEDULER_add_now (&attest_store_task, ash); +} + /** * Send a deletion success response * @@ -1742,6 +1882,10 @@ GNUNET_SERVICE_MAIN ( GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE, struct AttributeStoreMessage, NULL), + GNUNET_MQ_hd_var_size (attestation_store_message, + GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE, + struct AttributeStoreMessage, + NULL), GNUNET_MQ_hd_var_size (attribute_delete_message, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE, struct AttributeDeleteMessage, diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c index bb08e6385..9290925b8 100644 --- a/src/reclaim/plugin_rest_reclaim.c +++ b/src/reclaim/plugin_rest_reclaim.c @@ -241,210 +241,6 @@ struct RequestHandle json_t *resp_object; }; -/** - * Handle for attribute store request - */ -struct AttributeStoreHandle -{ - /** - * DLL - */ - struct AttributeStoreHandle *next; - - /** - * DLL - */ - struct AttributeStoreHandle *prev; - - /** - * Client connection - */ - struct IdpClient *client; - - /** - * Identity - */ - struct GNUNET_CRYPTO_EcdsaPrivateKey identity; - - /** - * Identity pubkey - */ - struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey; - - /** - * QueueEntry - */ - struct GNUNET_NAMESTORE_QueueEntry *ns_qe; - - /** - * The attribute to store - */ - struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim; - - /** - * The attestation to store - */ - struct GNUNET_RECLAIM_ATTESTATION_Claim *attest; - - /** - * The attribute expiration interval - */ - struct GNUNET_TIME_Relative exp; - - /** - * request id - */ - uint32_t r_id; -}; - -/** - * Handle for attribute deletion request - */ -struct AttributeDeleteHandle -{ - /** - * DLL - */ - struct AttributeDeleteHandle *next; - - /** - * DLL - */ - struct AttributeDeleteHandle *prev; - - /** - * Client connection - */ - struct IdpClient *client; - - /** - * Identity - */ - struct GNUNET_CRYPTO_EcdsaPrivateKey identity; - - - /** - * QueueEntry - */ - struct GNUNET_NAMESTORE_QueueEntry *ns_qe; - - /** - * Iterator - */ - struct GNUNET_NAMESTORE_ZoneIterator *ns_it; - - /** - * The attribute to delete - */ - struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim; - - /** - * The attestation to store - */ - struct GNUNET_RECLAIM_ATTESTATION_Claim *attest; - - /** - * Tickets to update - */ - struct TicketRecordsEntry *tickets_to_update_head; - - /** - * Tickets to update - */ - struct TicketRecordsEntry *tickets_to_update_tail; - - /** - * Attribute label - */ - char *label; - - /** - * request id - */ - uint32_t r_id; -}; - -/** - * Handle to the service. - */ -struct GNUNET_RECLAIM_Handle -{ - /** - * Configuration to use. - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Socket (if available). - */ - struct GNUNET_CLIENT_Connection *client; - - /** - * Closure for 'cb'. - */ - void *cb_cls; - - /** - * Head of active operations. - */ - struct GNUNET_RECLAIM_Operation *op_head; - - /** - * Tail of active operations. - */ - struct GNUNET_RECLAIM_Operation *op_tail; - - /** - * Head of active iterations - */ - struct GNUNET_RECLAIM_AttributeIterator *it_head; - - /** - * Tail of active iterations - */ - struct GNUNET_RECLAIM_AttributeIterator *it_tail; - - /** - * Head of active iterations - */ - struct GNUNET_RECLAIM_TicketIterator *ticket_it_head; - - /** - * Tail of active iterations - */ - struct GNUNET_RECLAIM_TicketIterator *ticket_it_tail; - - /** - * Currently pending transmission request, or NULL for none. - */ - struct GNUNET_CLIENT_TransmitHandle *th; - - /** - * Task doing exponential back-off trying to reconnect. - */ - struct GNUNET_SCHEDULER_Task *reconnect_task; - - /** - * Time for next connect retry. - */ - struct GNUNET_TIME_Relative reconnect_backoff; - - /** - * Connection to service (if available). - */ - struct GNUNET_MQ_Handle *mq; - - /** - * Request Id generator. Incremented by one for each request. - */ - uint32_t r_id_gen; - - /** - * Are we polling for incoming messages right now? - */ - int in_receive; -}; - /** * Cleanup lookup handle * @param handle Handle to clean up @@ -656,6 +452,8 @@ ticket_collect (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket) GNUNET_free (tmp); GNUNET_RECLAIM_ticket_iteration_next (handle->ticket_it); } + + static void add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle, const char *url, @@ -729,58 +527,12 @@ add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX); handle->idp = GNUNET_RECLAIM_connect (cfg); exp = GNUNET_TIME_UNIT_HOURS; - /*New */ - struct GNUNET_RECLAIM_Handle *h = handle->idp; - struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey = identity_priv; - /*struct GNUNET_RECLAIM_ATTESTATION_Claim *attr = attribute;*/ - struct GNUNET_TIME_Relative *exp_interval = &exp; - /*GNUNET_RECLAIM_ContinuationWithStatus cont = &finished_cont;*/ - void *cont_cls = handle; - - struct AttributeStoreHandle *ash; - struct GNUNET_GNSRECORD_Data rd[1]; - char *buf; - char *label; - size_t buf_size; - struct IdpClient *idp = cont_cls; - struct GNUNET_NAMESTORE_Handle *nsh; - nsh = GNUNET_NAMESTORE_connect (cfg); - if (NULL == nsh) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, - "error connecting to namestore"); - } - ash = GNUNET_new (struct AttributeStoreHandle); - ash->identity = *pkey; - ash->r_id = h->r_id_gen++; - ash->exp.rel_value_us = exp_interval->rel_value_us; - ash->attest = attribute; - ash->client = idp; - buf_size = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (ash->attest); - buf = GNUNET_malloc (buf_size); - // Give the ash a new id if unset - if (0 == ash->attest->id) - ash->attest->id - = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX); - GNUNET_RECLAIM_ATTESTATION_serialize (ash->attest, buf); - label = GNUNET_STRINGS_data_to_string_alloc (&ash->attest->id, - sizeof(uint64_t)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label); - - rd[0].data_size = buf_size; - rd[0].data = buf; - rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR; - rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; - rd[0].expiration_time = ash->exp.rel_value_us; - ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh, - &ash->identity, - label, - 1, - rd, - &finished_cont, - ash); - GNUNET_free (buf); - GNUNET_free (label); + handle->idp_op = GNUNET_RECLAIM_attestation_store (handle->idp, + identity_priv, + attribute, + &exp, + &finished_cont, + handle); GNUNET_JSON_parse_free (attrspec); } /*Placeholder*/ @@ -800,81 +552,9 @@ delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls) { - const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; - struct RequestHandle *handle = cls; - struct GNUNET_RECLAIM_ATTESTATION_Claim attr; - struct EgoEntry *ego_entry; - char *identity_id_str; - char *identity; - char *id; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting attestation.\n"); - if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) >= strlen ( - handle->url)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - identity_id_str = - strdup (handle->url + strlen ( - GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + 1); - identity = strtok (identity_id_str, "/"); - id = strtok (NULL, "/"); - if ((NULL == identity) || (NULL == id)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n"); - GNUNET_free (identity_id_str); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - for (ego_entry = handle->ego_head; NULL != ego_entry; - ego_entry = ego_entry->next) - if (0 == strcmp (identity, ego_entry->identifier)) - break; - handle->resp_object = json_array (); - if (NULL == ego_entry) - { - // Done - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity); - GNUNET_free (identity_id_str); - GNUNET_SCHEDULER_add_now (&return_response, handle); - return; - } - priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); - handle->idp = GNUNET_RECLAIM_connect (cfg); - memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim)); - GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(uint64_t)); - attr.name = ""; - - struct GNUNET_RECLAIM_Handle *h = handle->idp; - struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey = priv_key; - - struct AttributeDeleteHandle *adh; - struct IdpClient *idp = handle; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_DELETE message\n"); - struct GNUNET_NAMESTORE_Handle *nsh; - nsh = GNUNET_NAMESTORE_connect (cfg); - adh = GNUNET_new (struct AttributeDeleteHandle); - adh->attest = &attr; - adh->r_id = h->r_id_gen++; - adh->identity = *pkey; - adh->label = GNUNET_STRINGS_data_to_string_alloc (&adh->attest->id, - sizeof(uint64_t)); - /*GNUNET_SERVICE_client_continue (idp->client);*/ - adh->client = idp; - /*GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);*/ - adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh, - &adh->identity, - adh->label, - 0, - NULL, - &delete_finished_cb, - adh); - - - GNUNET_free (identity_id_str); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Deleting Attestations not supported\n"); + GNUNET_SCHEDULER_add_now (&do_error, cls); + return; } /** diff --git a/src/reclaim/reclaim_api.c b/src/reclaim/reclaim_api.c index 7d4d7588a..988650450 100644 --- a/src/reclaim/reclaim_api.c +++ b/src/reclaim/reclaim_api.c @@ -925,6 +925,52 @@ GNUNET_RECLAIM_attribute_delete ( return op; } +/** + * Store an attestation. If the attestation is already present, + * it is replaced with the new attestation. + * + * @param h handle to the re:claimID service + * @param pkey private key of the identity + * @param attr the attestation value + * @param exp_interval the relative expiration interval for the attestation + * @param cont continuation to call when done + * @param cont_cls closure for @a cont + * @return handle to abort the request + */ +struct GNUNET_RECLAIM_Operation * +GNUNET_RECLAIM_attestation_store ( + struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, + const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr, + const struct GNUNET_TIME_Relative *exp_interval, + GNUNET_RECLAIM_ContinuationWithStatus cont, + void *cont_cls) +{ + struct GNUNET_RECLAIM_Operation *op; + struct AttributeStoreMessage *sam; + size_t attr_len; + + op = GNUNET_new (struct GNUNET_RECLAIM_Operation); + op->h = h; + op->as_cb = cont; + op->cls = cont_cls; + op->r_id = h->r_id_gen++; + GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op); + attr_len = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (attr); + op->env = GNUNET_MQ_msg_extra (sam, + attr_len, + GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE); + sam->identity = *pkey; + sam->id = htonl (op->r_id); + sam->exp = GNUNET_htonll (exp_interval->rel_value_us); + + GNUNET_RECLAIM_ATTESTATION_serialize (attr, (char *) &sam[1]); + + sam->attr_len = htons (attr_len); + if (NULL != h->mq) + GNUNET_MQ_send_copy (h->mq, op->env); + return op; +} /** * List all attributes for a local identity. -- 2.25.1