From 1940b899b3620786b0265144ab756a3f05bcc8b0 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Thu, 16 Aug 2018 18:48:04 +0200 Subject: start zklaim service --- src/zklaim/Makefile.am | 47 ++- src/zklaim/plugin_reclaim_attribute_zklaim.c | 181 +++++++++++ src/zklaim/zklaim_api.c | 433 +++++++++++++++++++++++++++ src/zklaim/zklaim_api.h | 90 ++++++ 4 files changed, 749 insertions(+), 2 deletions(-) create mode 100644 src/zklaim/plugin_reclaim_attribute_zklaim.c create mode 100644 src/zklaim/zklaim_api.c create mode 100644 src/zklaim/zklaim_api.h (limited to 'src/zklaim') diff --git a/src/zklaim/Makefile.am b/src/zklaim/Makefile.am index a3432794a..1b25ac1a3 100644 --- a/src/zklaim/Makefile.am +++ b/src/zklaim/Makefile.am @@ -12,9 +12,51 @@ if USE_COVERAGE XLIB = -lgcov endif +plugin_LTLIBRARIES = \ + libgnunet_plugin_reclaim_attribute_zklaim.la -gnunet_zklaim_SOURCES = zklaim.c +lib_LTLIBRARIES = \ + libgnunetzklaim.la + +libgnunetzklaim_la_SOURCES = \ + zklaim_api.c \ + zklaim_api.h +libgnunetzklaim_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) $(XLIB) +libgnunetzklaim_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) $(WINFLAGS) \ + -version-info 0:0:0 + + +libgnunet_plugin_reclaim_attribute_zklaim_la_SOURCES = \ + plugin_reclaim_attribute_zklaim.c +libgnunet_plugin_reclaim_attribute_zklaim_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(LTLIBINTL) +libgnunet_plugin_reclaim_attribute_zklaim_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) + +test_zklaim_SOURCES = zklaim.c +test_zklaim_LDADD = \ + $(GCLIBADD)\ + $(LIBGCRYPT_LIBS) \ + -lzklaim \ + -lgcrypt \ + -lgmp \ + -lgmpxx \ + -lcrypto \ + -lprocps \ + -lstdc++ \ + -lm +test_zklaim_LDFLAGS = \ + $(GN_LIB_LDFLAGS) + +gnunet_zklaim_SOURCES = gnunet-zklaim.c gnunet_zklaim_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/identity/libgnunetidentity.la \ + libgnunetzklaim.la \ $(GCLIBADD)\ $(LIBGCRYPT_LIBS) \ -lzklaim \ @@ -28,8 +70,9 @@ gnunet_zklaim_LDADD = \ gnunet_zklaim_LDFLAGS = \ $(GN_LIB_LDFLAGS) -#lib_LTLIBRARIES = libgnunetzklaim.la bin_PROGRAMS = gnunet-zklaim +#lib_LTLIBRARIES = libgnunetzklaim.la +check_PROGRAMS = test_zklaim if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; diff --git a/src/zklaim/plugin_reclaim_attribute_zklaim.c b/src/zklaim/plugin_reclaim_attribute_zklaim.c new file mode 100644 index 000000000..a79576cb1 --- /dev/null +++ b/src/zklaim/plugin_reclaim_attribute_zklaim.c @@ -0,0 +1,181 @@ +/* + This file is part of GNUnet + Copyright (C) 2013, 2014, 2016 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @file zklaim/plugin_reclaim_attribute_zklaim.c + * @brief identity attribute plugin to provide the API for ZKlaims + * + * @author Martin Schanzenbach + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_reclaim_attribute_plugin.h" +#include + + +/** + * Convert the 'value' of an attribute to a string. + * + * @param cls closure, unused + * @param type type of the attribute + * @param data value in binary encoding + * @param data_size number of bytes in @a data + * @return NULL on error, otherwise human-readable representation of the value + */ +static char * +zklaim_value_to_string (void *cls, + uint32_t type, + const void *data, + size_t data_size) +{ + + switch (type) + { + case GNUNET_RECLAIM_ATTRIBUTE_TYPE_ZKLAIM: + return GNUNET_strndup (data, data_size); + default: + return NULL; + } +} + + +/** + * Convert human-readable version of a 'value' of an attribute to the binary + * representation. + * + * @param cls closure, unused + * @param type type of the attribute + * @param s human-readable string + * @param data set to value in binary encoding (will be allocated) + * @param data_size set to number of bytes in @a data + * @return #GNUNET_OK on success + */ +static int +zklaim_string_to_value (void *cls, + uint32_t type, + const char *s, + void **data, + size_t *data_size) +{ + if (NULL == s) + return GNUNET_SYSERR; + switch (type) + { + + case GNUNET_RECLAIM_ATTRIBUTE_TYPE_ZKLAIM: + *data = GNUNET_strdup (s); + *data_size = strlen (s); + return GNUNET_OK; + default: + return GNUNET_SYSERR; + } +} + + +/** + * Mapping of attribute type numbers to human-readable + * attribute type names. + */ +static struct { + const char *name; + uint32_t number; +} zklaim_name_map[] = { + { "ZKLAIM", GNUNET_RECLAIM_ATTRIBUTE_TYPE_ZKLAIM }, + { NULL, UINT32_MAX } +}; + + +/** + * Convert a type name to the corresponding number. + * + * @param cls closure, unused + * @param zklaim_typename name to convert + * @return corresponding number, UINT32_MAX on error + */ +static uint32_t +zklaim_typename_to_number (void *cls, + const char *zklaim_typename) +{ + unsigned int i; + + i=0; + while ( (NULL != zklaim_name_map[i].name) && + (0 != strcasecmp (zklaim_typename, + zklaim_name_map[i].name)) ) + i++; + return zklaim_name_map[i].number; +} + + +/** + * Convert a type number (i.e. 1) to the corresponding type string + * + * @param cls closure, unused + * @param type number of a type to convert + * @return corresponding typestring, NULL on error + */ +static const char * +zklaim_number_to_typename (void *cls, + uint32_t type) +{ + unsigned int i; + + i=0; + while ( (NULL != zklaim_name_map[i].name) && + (type != zklaim_name_map[i].number) ) + i++; + return zklaim_name_map[i].name; +} + + +/** + * Entry point for the plugin. + * + * @param cls NULL + * @return the exported block API + */ +void * +libgnunet_plugin_reclaim_attribute_zklaim_init (void *cls) +{ + struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api; + + api = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions); + api->value_to_string = &zklaim_value_to_string; + api->string_to_value = &zklaim_string_to_value; + api->typename_to_number = &zklaim_typename_to_number; + api->number_to_typename = &zklaim_number_to_typename; + return api; +} + + +/** + * Exit point from the plugin. + * + * @param cls the return value from #libgnunet_plugin_block_test_init() + * @return NULL + */ +void * +libgnunet_plugin_reclaim_attribute_zklaim_done (void *cls) +{ + struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api = cls; + + GNUNET_free (api); + return NULL; +} + +/* end of plugin_reclaim_attribute_type_zklaim.c */ diff --git a/src/zklaim/zklaim_api.c b/src/zklaim/zklaim_api.c new file mode 100644 index 000000000..f54ede342 --- /dev/null +++ b/src/zklaim/zklaim_api.c @@ -0,0 +1,433 @@ +/* + This file is part of GNUnet. + Copyright (C) 2013, 2016 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @file zklaim/zklaim_api.c + * @brief api to interact with the zklaim service + * @author Martin Schanzenbach + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_constants.h" +#include "gnunet_protocols.h" +#include "gnunet_zklaim_service.h" +#include "zklaim/zklaim.h" +#include "zklaim_api.h" + +#define LOG(kind,...) GNUNET_log_from (kind, "zklaim-api",__VA_ARGS__) + +/** + * Handle for an ego. + */ +struct GNUNET_ZKLAIM_Context +{ + /** + * ZKlaim context. + */ + struct zklaim_ctx *zk_ctx; + + /** + * Current name associated with this context. + */ + char *name; + + /** + * Attributes associated with context + */ + char *attrs; + + /** + * Client context associated with this ego. + */ + void *ctx; + +}; + + +/** + * Handle for an operation with the service. + */ +struct GNUNET_ZKLAIM_Operation +{ + + /** + * Main handle. + */ + struct GNUNET_ZKLAIM_Handle *h; + + /** + * We keep operations in a DLL. + */ + struct GNUNET_ZKLAIM_Operation *next; + + /** + * We keep operations in a DLL. + */ + struct GNUNET_ZKLAIM_Operation *prev; + + /** + * Message to send to the zklaim service. + * Allocated at the end of this struct. + */ + const struct GNUNET_MessageHeader *msg; + + /** + * Continuation to invoke with the result of the transmission; @e cb + * will be NULL in this case. + */ + GNUNET_ZKLAIM_ContinuationWithStatus cont; + + /** + * Closure for @e cont or @e cb. + */ + void *cls; + +}; + + +/** + * Handle for the service. + */ +struct GNUNET_ZKLAIM_Handle +{ + /** + * Configuration to use. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Connection to service. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * Hash map from the hash of the public key to the + * respective `GNUNET_ZKLAIM_Ego` handle. + */ + struct GNUNET_CONTAINER_MultiHashMap *egos; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Head of active operations. + */ + struct GNUNET_ZKLAIM_Operation *op_head; + + /** + * Tail of active operations. + */ + struct GNUNET_ZKLAIM_Operation *op_tail; + + /** + * Task doing exponential back-off trying to reconnect. + */ + struct GNUNET_SCHEDULER_Task *reconnect_task; + + /** + * Time for next connect retry. + */ + struct GNUNET_TIME_Relative reconnect_delay; + +}; + + +/** + * Try again to connect to the zklaim service. + * + * @param cls handle to the zklaim service. + */ +static void +reconnect (void *cls); + +/** + * Reschedule a connect attempt to the service. + * + * @param h transport service to reconnect + */ +static void +reschedule_connect (struct GNUNET_ZKLAIM_Handle *h) +{ + struct GNUNET_ZKLAIM_Operation *op; + + GNUNET_assert (NULL == h->reconnect_task); + + if (NULL != h->mq) + { + GNUNET_MQ_destroy (h->mq); + h->mq = NULL; + } + while (NULL != (op = h->op_head)) + { + GNUNET_CONTAINER_DLL_remove (h->op_head, + h->op_tail, + op); + if (NULL != op->cont) + op->cont (op->cls, + GNUNET_SYSERR, + "Error in communication with the zklaim service"); + GNUNET_free (op); + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Scheduling task to reconnect to zklaim service in %s.\n", + GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay, + GNUNET_YES)); + h->reconnect_task = + GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, + &reconnect, + h); + h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay); +} + + +/** + * Generic error handler, called with the appropriate error code and + * the same closure specified at the creation of the message queue. + * Not every message queue implementation supports an error handler. + * + * @param cls closure with the `struct GNUNET_ZKLAIM_Handle *` + * @param error error code + */ +static void +mq_error_handler (void *cls, + enum GNUNET_MQ_Error error) +{ + struct GNUNET_ZKLAIM_Handle *h = cls; + + reschedule_connect (h); +} + + +/** + * We received a result code from the service. Check the message + * is well-formed. + * + * @param cls closure + * @param rcm result message received + * @return #GNUNET_OK if the message is well-formed + */ +static int +check_zklaim_result_code (void *cls, + const struct ResultCodeMessage *rcm) +{ + uint16_t size = ntohs (rcm->header.size) - sizeof (*rcm); + const char *str = (const char *) &rcm[1]; + + if (0 == size) + return GNUNET_OK; + if ('\0' != str[size - 1]) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * We received a result code from the service. + * + * @param cls closure + * @param rcm result message received + */ +static void +handle_zklaim_result_code (void *cls, + const struct ResultCodeMessage *rcm) +{ + struct GNUNET_ZKLAIM_Handle *h = cls; + struct GNUNET_ZKLAIM_Operation *op; + uint16_t size = ntohs (rcm->header.size) - sizeof (*rcm); + const char *str = (0 == size) ? NULL : (const char *) &rcm[1]; + + op = h->op_head; + if (NULL == op) + { + GNUNET_break (0); + reschedule_connect (h); + return; + } + GNUNET_CONTAINER_DLL_remove (h->op_head, + h->op_tail, + op); + if (NULL != op->cont) + op->cont (op->cls, + GNUNET_OK, + str); + GNUNET_free (op); +} + + +/** + * Try again to connect to the zklaim service. + * + * @param cls handle to the zklaim service. + */ +static void +reconnect (void *cls) +{ + struct GNUNET_ZKLAIM_Handle *h = cls; + struct GNUNET_MQ_MessageHandler handlers[] = { + GNUNET_MQ_hd_var_size (zklaim_result_code, + GNUNET_MESSAGE_TYPE_ZKLAIM_RESULT_CODE, + struct ResultCodeMessage, + h), + GNUNET_MQ_handler_end () + }; + + h->reconnect_task = NULL; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Connecting to zklaim service.\n"); + GNUNET_assert (NULL == h->mq); + h->mq = GNUNET_CLIENT_connect (h->cfg, + "zklaim", + handlers, + &mq_error_handler, + h); + if (NULL == h->mq) + return; +} + + +/** + * Connect to the zklaim service. + * + * @param cfg the configuration to use + * @param cb function to call on all zklaim events, can be NULL + * @param cb_cls closure for @a cb + * @return handle to use + */ +struct GNUNET_ZKLAIM_Handle * +GNUNET_ZKLAIM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct GNUNET_ZKLAIM_Handle *h; + + h = GNUNET_new (struct GNUNET_ZKLAIM_Handle); + h->cfg = cfg; + reconnect (h); + if (NULL == h->mq) + { + GNUNET_free (h); + return NULL; + } + return h; +} + + +/** + * Create a new zklaim with the given name. + * + * @param h zklaim service to use + * @param name desired name + * @param cont function to call with the result (will only be called once) + * @param cont_cls closure for @a cont + * @return handle to abort the operation + */ +struct GNUNET_ZKLAIM_Operation * +GNUNET_ZKLAIM_context_create (struct GNUNET_ZKLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk, + const char *name, + const char *attr_list, + GNUNET_ZKLAIM_ContinuationWithStatus cont, + void *cont_cls) +{ + struct GNUNET_ZKLAIM_Operation *op; + struct GNUNET_MQ_Envelope *env; + struct CreateRequestMessage *crm; + size_t slen; + + if (NULL == h->mq) + return NULL; + slen = strlen (name) + 1; + if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct CreateRequestMessage)) + { + GNUNET_break (0); + return NULL; + } + op = GNUNET_new (struct GNUNET_ZKLAIM_Operation); + op->h = h; + op->cont = cont; + op->cls = cont_cls; + GNUNET_CONTAINER_DLL_insert_tail (h->op_head, + h->op_tail, + op); + env = GNUNET_MQ_msg_extra (crm, + slen, + GNUNET_MESSAGE_TYPE_ZKLAIM_CREATE); + crm->name_len = htons (slen); + crm->reserved = htons (0); + crm->private_key = *pk; + GNUNET_memcpy (&crm[1], + name, + slen); + GNUNET_MQ_send (h->mq, + env); + //TODO add attrs + return op; +} + + +/** + * Cancel an zklaim operation. Note that the operation MAY still + * be executed; this merely cancels the continuation; if the request + * was already transmitted, the service may still choose to complete + * the operation. + * + * @param op operation to cancel + */ +void +GNUNET_ZKLAIM_cancel (struct GNUNET_ZKLAIM_Operation *op) +{ + op->cont = NULL; +} + + +/** + * Disconnect from zklaim service + * + * @param h handle to destroy + */ +void +GNUNET_ZKLAIM_disconnect (struct GNUNET_ZKLAIM_Handle *h) +{ + struct GNUNET_ZKLAIM_Operation *op; + + GNUNET_assert (NULL != h); + if (h->reconnect_task != NULL) + { + GNUNET_SCHEDULER_cancel (h->reconnect_task); + h->reconnect_task = NULL; + } + while (NULL != (op = h->op_head)) + { + GNUNET_break (NULL == op->cont); + GNUNET_CONTAINER_DLL_remove (h->op_head, + h->op_tail, + op); + GNUNET_free (op); + } + if (NULL != h->mq) + { + GNUNET_MQ_destroy (h->mq); + h->mq = NULL; + } + GNUNET_free (h); +} + +/* end of zklaim_api.c */ diff --git a/src/zklaim/zklaim_api.h b/src/zklaim/zklaim_api.h new file mode 100644 index 000000000..77053c667 --- /dev/null +++ b/src/zklaim/zklaim_api.h @@ -0,0 +1,90 @@ +/* + This file is part of GNUnet. + Copyright (C) 2013 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @author Martin Schanzenbach + * @file zklaim/zklaim.h + * + * @brief Common type definitions for the zklaim + * service and API. + */ +#ifndef ZKLAIM_API_H +#define ZKLAIM_API_H + +#include "gnunet_common.h" + + +GNUNET_NETWORK_STRUCT_BEGIN + + +/** + * Answer from service to client about last operation; + * GET_DEFAULT maybe answered with this message on failure; + * CREATE and RENAME will always be answered with this message. + */ +struct ResultCodeMessage +{ + /** + * Type: #GNUNET_MESSAGE_TYPE_ZKLAIM_RESULT_CODE + */ + struct GNUNET_MessageHeader header; + + /** + * Status code for the last operation, in NBO. + * (currently not used). + */ + uint32_t result_code GNUNET_PACKED; + + /* followed by 0-terminated error message (on error) */ + +}; + + +/** + * Client requests creation of an identity. Service + * will respond with a result code. + */ +struct CreateRequestMessage +{ + /** + * Type: #GNUNET_MESSAGE_TYPE_ZKLAIM_CREATE + */ + struct GNUNET_MessageHeader header; + + /** + * Number of bytes in identity name string including 0-termination, in NBO. + */ + uint16_t name_len GNUNET_PACKED; + + /** + * Always zero. + */ + uint16_t reserved GNUNET_PACKED; + + /** + * The private key + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey private_key; + + /* followed by 0-terminated identity name */ + +}; + +GNUNET_NETWORK_STRUCT_END + +#endif -- cgit v1.2.3