From 1d468ecabd6c2ee5c0eae672292efa0f51bc9e48 Mon Sep 17 00:00:00 2001 From: Andreas Ebner Date: Mon, 7 Oct 2019 11:48:07 +0200 Subject: Renamed credential service to abd, replaced all related functions, parameters, etc --- src/abd/Makefile.am | 111 ++ src/abd/abd.conf.in | 5 + src/abd/abd.h | 290 +++++ src/abd/abd_api.c | 556 ++++++++++ src/abd/abd_serialization.c | 508 +++++++++ src/abd/abd_serialization.h | 165 +++ src/abd/delegate_misc.c | 274 +++++ src/abd/delegate_misc.h | 36 + src/abd/gnunet-abd.c | 1070 +++++++++++++++++++ src/abd/gnunet-service-abd.c | 1751 +++++++++++++++++++++++++++++++ src/abd/plugin_gnsrecord_abd.c | 349 ++++++ src/abd/plugin_rest_credential.c | 1174 +++++++++++++++++++++ src/abd/test_abd_bi_and.sh | 98 ++ src/abd/test_abd_bi_and2.sh | 94 ++ src/abd/test_abd_bi_and3.sh | 96 ++ src/abd/test_abd_bi_and4.sh | 83 ++ src/abd/test_abd_bi_bw.sh | 87 ++ src/abd/test_abd_bi_bw_link.sh | 92 ++ src/abd/test_abd_bi_bw_link2.sh | 93 ++ src/abd/test_abd_bi_fw.sh | 92 ++ src/abd/test_abd_defaults.conf | 24 + src/abd/test_abd_issue.sh | 46 + src/abd/test_abd_lookup.conf | 28 + src/abd/test_abd_own.sh | 140 +++ src/abd/test_abd_verify.sh | 87 ++ src/abd/test_abd_verify_and.sh | 86 ++ src/abd/test_abd_verify_simple.sh | 56 + src/abd/test_credential_collect.sh | 47 + src/abd/test_credential_collect_rest.sh | 91 ++ src/abd/test_credential_issue_rest.sh | 53 + src/abd/test_credential_verify_rest.sh | 88 ++ 31 files changed, 7770 insertions(+) create mode 100644 src/abd/Makefile.am create mode 100644 src/abd/abd.conf.in create mode 100644 src/abd/abd.h create mode 100644 src/abd/abd_api.c create mode 100644 src/abd/abd_serialization.c create mode 100644 src/abd/abd_serialization.h create mode 100644 src/abd/delegate_misc.c create mode 100644 src/abd/delegate_misc.h create mode 100644 src/abd/gnunet-abd.c create mode 100644 src/abd/gnunet-service-abd.c create mode 100644 src/abd/plugin_gnsrecord_abd.c create mode 100644 src/abd/plugin_rest_credential.c create mode 100755 src/abd/test_abd_bi_and.sh create mode 100755 src/abd/test_abd_bi_and2.sh create mode 100755 src/abd/test_abd_bi_and3.sh create mode 100755 src/abd/test_abd_bi_and4.sh create mode 100755 src/abd/test_abd_bi_bw.sh create mode 100755 src/abd/test_abd_bi_bw_link.sh create mode 100755 src/abd/test_abd_bi_bw_link2.sh create mode 100755 src/abd/test_abd_bi_fw.sh create mode 100644 src/abd/test_abd_defaults.conf create mode 100755 src/abd/test_abd_issue.sh create mode 100644 src/abd/test_abd_lookup.conf create mode 100755 src/abd/test_abd_own.sh create mode 100755 src/abd/test_abd_verify.sh create mode 100755 src/abd/test_abd_verify_and.sh create mode 100755 src/abd/test_abd_verify_simple.sh create mode 100755 src/abd/test_credential_collect.sh create mode 100755 src/abd/test_credential_collect_rest.sh create mode 100755 src/abd/test_credential_issue_rest.sh create mode 100755 src/abd/test_credential_verify_rest.sh (limited to 'src/abd') diff --git a/src/abd/Makefile.am b/src/abd/Makefile.am new file mode 100644 index 000000000..321fb0350 --- /dev/null +++ b/src/abd/Makefile.am @@ -0,0 +1,111 @@ +# This Makefile.am is in the public domain +AM_CPPFLAGS = -I$(top_srcdir)/src/include + +EXTRA_DIST = \ + test_abd_defaults.conf \ + test_abd_lookup.conf + + +if USE_COVERAGE + AM_CFLAGS = --coverage -O0 +endif + +pkgcfgdir = $(pkgdatadir)/config.d/ + +libexecdir= $(pkglibdir)/libexec/ + +plugindir = $(libdir)/gnunet + +pkgcfg_DATA = \ + abd.conf + + +# /usr/lib - compiles a layer which can be used to be communicagte with the service +lib_LTLIBRARIES = \ + libgnunetabd.la + +# /usr/lib/gnunet/libexec - Business logic . Separate process +libexec_PROGRAMS = \ + gnunet-service-abd + +bin_PROGRAMS = \ + gnunet-abd + +plugin_LTLIBRARIES = \ + libgnunet_plugin_gnsrecord_abd.la + + +gnunet_abd_SOURCES = \ + gnunet-abd.c +gnunet_abd_LDADD = \ + libgnunetabd.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ + $(top_builddir)/src/identity/libgnunetidentity.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(GN_LIBINTL) + + +libgnunet_plugin_gnsrecord_abd_la_SOURCES = \ + plugin_gnsrecord_abd.c +libgnunet_plugin_gnsrecord_abd_la_LIBADD = \ + libgnunetabd.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(LTLIBINTL) +libgnunet_plugin_gnsrecord_abd_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) + + + +gnunet_service_abd_SOURCES = \ + gnunet-service-abd.c +gnunet_service_abd_LDADD = \ + libgnunetabd.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(GN_LIBINTL) + + +libgnunetabd_la_SOURCES = \ + abd_api.c abd.h\ + abd_serialization.c \ + abd_serialization.h \ + delegate_misc.c \ + delegate_misc.h +libgnunetabd_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la $(XLIB) +libgnunetabd_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) + + + +check_SCRIPTS = \ + test_abd_issue.sh \ + test_abd_verify_simple.sh \ + test_abd_verify.sh \ + test_abd_verify_and.sh + +if ENABLE_TEST_RUN +if HAVE_SQLITE + AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; + TESTS = $(check_SCRIPTS) +endif +endif + +#libgnunet_plugin_rest_abd_la_SOURCES = \ +# plugin_rest_abd.c +#libgnunet_plugin_rest_abd_la_LIBADD = \ +# $(top_builddir)/src/abd/libgnunetabd.la \ +# $(top_builddir)/src/rest/libgnunetrest.la \ +# $(top_builddir)/src/identity/libgnunetidentity.la \ +# $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ +# $(LTLIBINTL) -ljansson -lmicrohttpd +#libgnunet_plugin_rest_abd_la_LDFLAGS = \ +# $(GN_PLUGIN_LDFLAGS) + + + + + diff --git a/src/abd/abd.conf.in b/src/abd/abd.conf.in new file mode 100644 index 000000000..7baf95fc8 --- /dev/null +++ b/src/abd/abd.conf.in @@ -0,0 +1,5 @@ +[abd] +BINARY = gnunet-service-abd +UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-abd.sock +RUN_PER_USER = YES +OPTIONS = -L DEBUG diff --git a/src/abd/abd.h b/src/abd/abd.h new file mode 100644 index 000000000..854814832 --- /dev/null +++ b/src/abd/abd.h @@ -0,0 +1,290 @@ +/* + This file is part of GNUnet + Copyright (C) 2012-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 . + + SPDX-License-Identifier: AGPL3.0-or-later + */ +/** + * @file abd/abd.h + * @brief IPC messages between ABD API and ABD service + * @author Martin Schanzenbach + */ +#ifndef ABD_H +#define ABD_H + +#include "gnunet_abd_service.h" + +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * Message from client to Credential service to collect credentials. + */ +struct CollectMessage +{ + /** + * Header of type #GNUNET_MESSAGE_TYPE_ABD_VERIFY + */ + struct GNUNET_MessageHeader header; + + /** + * Subject public key + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey subject_key; + + /** + * Trust anchor + */ + struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key; + + /** + * Length of the issuer attribute + */ + uint16_t issuer_attribute_len; + + /** + * Direction of the resolution algo + */ + uint16_t resolution_algo; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; + + /* Followed by the zero-terminated attribute */ +}; + + +/** + * Message from client to Credential service to verify attributes. + */ +struct VerifyMessage +{ + /** + * Header of type #GNUNET_MESSAGE_TYPE_ABD_VERIFY + */ + struct GNUNET_MessageHeader header; + + /** + * Subject public key + */ + struct GNUNET_CRYPTO_EcdsaPublicKey subject_key; + + /** + * Trust anchor + */ + struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key; + + /** + * Number of delegates + */ + uint32_t d_count; + + /** + * Length of the issuer attribute + */ + uint16_t issuer_attribute_len; + + /** + * Direction of the resolution algo + */ + uint16_t resolution_algo; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; + + /* Followed by the zero-terminated attribute and credentials to look up */ +}; + + +/** + * Message from ABD service to client: new results. + */ +struct DelegationChainResultMessage +{ + /** + * Header of type #GNUNET_MESSAGE_TYPE_ABD_VERIFY_RESULT + */ + struct GNUNET_MessageHeader header; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; + + /** + * Indicates if credential has been found at all + */ + uint32_t del_found GNUNET_PACKED; + + /** + * The number of delegations in the response + */ + uint32_t d_count GNUNET_PACKED; + + /** + * The number of credentials in the response + */ + uint32_t c_count GNUNET_PACKED; + + /* followed by ad_count GNUNET_ABD_RecordData structs*/ +}; + +/** + * Message from ABD service to client: new results. + */ +struct DelegationChainIntermediateMessage +{ + /** + * Header of type #GNUNET_MESSAGE_TYPE_ABD_INTERMEDIATE_RESULT + */ + struct GNUNET_MessageHeader header; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; + + uint16_t is_bw GNUNET_PACKED; + + uint32_t size GNUNET_PACKED; +}; + +struct DelegationRecordData +{ + /** + * Subject key + */ + struct GNUNET_CRYPTO_EcdsaPublicKey subject_key; + + /** + * Subject attributes + */ + uint32_t subject_attribute_len GNUNET_PACKED; +}; + + +struct ChainEntry +{ + /** + * Issuer key + */ + struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key; + + /** + * Subject key + */ + struct GNUNET_CRYPTO_EcdsaPublicKey subject_key; + + /** + * Issuer attributes + */ + uint32_t issuer_attribute_len GNUNET_PACKED; + + /** + * Subject attributes + */ + uint32_t subject_attribute_len GNUNET_PACKED; +}; + + +struct CredentialEntry +{ + + /** + * The signature for this credential by the issuer + */ + struct GNUNET_CRYPTO_EcdsaSignature signature; + + /** + * Signature meta + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * Public key of the issuer + */ + struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key; + + /** + * Public key of the subject this credential was issued to + */ + struct GNUNET_CRYPTO_EcdsaPublicKey subject_key; + + /** + * Expiration time of this credential + */ + uint64_t expiration GNUNET_PACKED; + + /** + * Issuer attribute length + */ + uint32_t issuer_attribute_len; + + /** + * Followed by the attribute string + */ +}; + +struct DelegateEntry +{ + + /** + * The signature for this credential by the issuer + */ + struct GNUNET_CRYPTO_EcdsaSignature signature; + + /** + * Signature meta + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * Public key of the issuer + */ + struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key; + + /** + * Public key of the subject this credential was issued to + */ + struct GNUNET_CRYPTO_EcdsaPublicKey subject_key; + + /** + * Expiration time of this credential + */ + uint64_t expiration GNUNET_PACKED; + + /** + * Issuer subject attribute length + */ + uint32_t issuer_attribute_len; + + /** + * Issuer attribute length + */ + uint32_t subject_attribute_len; + + /** + * Followed by the subject attribute string + */ +}; + + +GNUNET_NETWORK_STRUCT_END + +#endif diff --git a/src/abd/abd_api.c b/src/abd/abd_api.c new file mode 100644 index 000000000..cdc52df91 --- /dev/null +++ b/src/abd/abd_api.c @@ -0,0 +1,556 @@ +/* + This file is part of GNUnet. + Copyright (C) 2009-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 . + + SPDX-License-Identifier: AGPL3.0-or-later +*/ +/** + * @file abd/abd_api.c + * @brief library to access the ABD service + * @author Martin Schanzenbach + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_constants.h" +#include "gnunet_arm_service.h" +#include "gnunet_hello_lib.h" +#include "gnunet_protocols.h" +#include "gnunet_signatures.h" +#include "abd.h" +#include "abd_serialization.h" +#include "gnunet_abd_service.h" +#include "gnunet_identity_service.h" + + +#define LOG(kind, ...) GNUNET_log_from (kind, "abd-api", __VA_ARGS__) + +/** + * Handle to a verify request + */ +struct GNUNET_ABD_Request +{ + + /** + * DLL + */ + struct GNUNET_ABD_Request *next; + + /** + * DLL + */ + struct GNUNET_ABD_Request *prev; + + /** + * handle to abd service + */ + struct GNUNET_ABD_Handle *abd_handle; + + /** + * processor to call on verify result + */ + GNUNET_ABD_CredentialResultProcessor verify_proc; + + /** + * @e verify_proc closure + */ + void *proc_cls; + + /** + * processor to call on intermediate result + */ + GNUNET_ABD_IntermediateResultProcessor int_proc; + + /** + * @e verify_proc2 closure + */ + void *proc2_cls; + + /** + * Envelope with the message for this queue entry. + */ + struct GNUNET_MQ_Envelope *env; + + /** + * request id + */ + uint32_t r_id; +}; + + +/** + * Connection to the ABD service. + */ +struct GNUNET_ABD_Handle +{ + + /** + * Configuration to use. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Connection to service (if available). + */ + struct GNUNET_MQ_Handle *mq; + + /** + * Head of linked list of active verify requests. + */ + struct GNUNET_ABD_Request *request_head; + + /** + * Tail of linked list of active verify requests. + */ + struct GNUNET_ABD_Request *request_tail; + + /** + * Reconnect task + */ + struct GNUNET_SCHEDULER_Task *reconnect_task; + + /** + * How long do we wait until we try to reconnect? + */ + struct GNUNET_TIME_Relative reconnect_backoff; + + /** + * Request Id generator. Incremented by one for each request. + */ + uint32_t r_id_gen; +}; + + +/** + * Reconnect to ABD service. + * + * @param handle the handle to the ABD service + */ +static void +reconnect (struct GNUNET_ABD_Handle *handle); + + +/** + * Reconnect to ABD + * + * @param cls the handle + */ +static void +reconnect_task (void *cls) +{ + struct GNUNET_ABD_Handle *handle = cls; + + handle->reconnect_task = NULL; + reconnect (handle); +} + + +/** + * Disconnect from service and then reconnect. + * + * @param handle our handle + */ +static void +force_reconnect (struct GNUNET_ABD_Handle *handle) +{ + GNUNET_MQ_destroy (handle->mq); + handle->mq = NULL; + handle->reconnect_backoff = + GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff); + handle->reconnect_task = + GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff, + &reconnect_task, + handle); +} + + +/** + * 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_ABD_Handle *` + * @param error error code + */ +static void +mq_error_handler (void *cls, enum GNUNET_MQ_Error error) +{ + struct GNUNET_ABD_Handle *handle = cls; + + force_reconnect (handle); +} + +/** + * Check validity of message received from the ABD service + * + * @param cls the `struct GNUNET_ABD_Handle *` + * @param vr_msg the incoming message + */ +static int +check_result (void *cls, const struct DelegationChainResultMessage *vr_msg) +{ + //TODO + return GNUNET_OK; +} + + +/** + * Handler for messages received from the ABD service + * + * @param cls the `struct GNUNET_ABD_Handle *` + * @param vr_msg the incoming message + */ +static void +handle_result (void *cls, const struct DelegationChainResultMessage *vr_msg) +{ + struct GNUNET_ABD_Handle *handle = cls; + uint32_t r_id = ntohl (vr_msg->id); + struct GNUNET_ABD_Request *vr; + size_t mlen = ntohs (vr_msg->header.size) - sizeof (*vr_msg); + uint32_t d_count = ntohl (vr_msg->d_count); + uint32_t c_count = ntohl (vr_msg->c_count); + struct GNUNET_ABD_Delegation d_chain[d_count]; + struct GNUNET_ABD_Delegate dels[c_count]; + GNUNET_ABD_CredentialResultProcessor proc; + void *proc_cls; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received verify reply from ABD service\n"); + for (vr = handle->request_head; NULL != vr; vr = vr->next) + if (vr->r_id == r_id) + break; + if (NULL == vr) + return; + proc = vr->verify_proc; + proc_cls = vr->proc_cls; + GNUNET_CONTAINER_DLL_remove (handle->request_head, handle->request_tail, vr); + GNUNET_MQ_discard (vr->env); + GNUNET_free (vr); + GNUNET_assert ( + GNUNET_OK == + GNUNET_ABD_delegation_chain_deserialize (mlen, + (const char *) &vr_msg[1], + d_count, + d_chain, + c_count, + dels)); + if (GNUNET_NO == ntohl (vr_msg->del_found)) + { + proc (proc_cls, 0, NULL, 0, + NULL); + } + else + { + proc (proc_cls, d_count, d_chain, c_count, dels); + } +} + +static int +check_intermediate (void *cls, const struct DelegationChainIntermediateMessage *vr_msg) +{ + //TODO + return GNUNET_OK; +} + +static void +handle_intermediate (void *cls, const struct DelegationChainIntermediateMessage *vr_msg) +{ + struct GNUNET_ABD_Handle *handle = cls; + uint32_t r_id = ntohl (vr_msg->id); + uint32_t size = ntohl (vr_msg->size); + bool is_bw = ntohs(vr_msg->is_bw); + struct GNUNET_ABD_Request *vr; + GNUNET_ABD_IntermediateResultProcessor proc; + void *proc_cls; + struct GNUNET_ABD_Delegation *dd; + + + LOG (GNUNET_ERROR_TYPE_DEBUG, "Received intermediate reply from ABD service\n"); + + for (vr = handle->request_head; NULL != vr; vr = vr->next) + if (vr->r_id == r_id) + break; + if (NULL == vr) + return; + + proc = vr->int_proc; + proc_cls = vr->proc2_cls; + + dd = GNUNET_new (struct GNUNET_ABD_Delegation); + GNUNET_assert ( + GNUNET_OK == + GNUNET_ABD_delegation_chain_deserialize (size, + (const char *) &vr_msg[1], + 1, + dd, + 0, + NULL)); + proc (proc_cls, dd, is_bw); +} + + + +/** + * Reconnect to ABD service. + * + * @param handle the handle to the ABD service + */ +static void +reconnect (struct GNUNET_ABD_Handle *handle) +{ + struct GNUNET_MQ_MessageHandler handlers[] = + {GNUNET_MQ_hd_var_size (result, + GNUNET_MESSAGE_TYPE_ABD_VERIFY_RESULT, + struct DelegationChainResultMessage, + handle), + GNUNET_MQ_hd_var_size (result, + GNUNET_MESSAGE_TYPE_ABD_COLLECT_RESULT, + struct DelegationChainResultMessage, + handle), + GNUNET_MQ_hd_var_size (intermediate, + GNUNET_MESSAGE_TYPE_ABD_INTERMEDIATE_RESULT, + struct DelegationChainIntermediateMessage, + handle), + GNUNET_MQ_handler_end ()}; + struct GNUNET_ABD_Request *vr; + + GNUNET_assert (NULL == handle->mq); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying to connect to ABD\n"); + handle->mq = GNUNET_CLIENT_connect (handle->cfg, + "abd", + handlers, + &mq_error_handler, + handle); + if (NULL == handle->mq) + return; + for (vr = handle->request_head; NULL != vr; vr = vr->next) + GNUNET_MQ_send_copy (handle->mq, vr->env); +} + + +/** + * Initialize the connection with the ABD service. + * + * @param cfg configuration to use + * @return handle to the ABD service, or NULL on error + */ +struct GNUNET_ABD_Handle * +GNUNET_ABD_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct GNUNET_ABD_Handle *handle; + + handle = GNUNET_new (struct GNUNET_ABD_Handle); + handle->cfg = cfg; + reconnect (handle); + if (NULL == handle->mq) + { + GNUNET_free (handle); + return NULL; + } + return handle; +} + + +/** + * Shutdown connection with the ABD service. + * + * @param handle handle of the ABD connection to stop + */ +void +GNUNET_ABD_disconnect (struct GNUNET_ABD_Handle *handle) +{ + if (NULL != handle->mq) + { + GNUNET_MQ_destroy (handle->mq); + handle->mq = NULL; + } + if (NULL != handle->reconnect_task) + { + GNUNET_SCHEDULER_cancel (handle->reconnect_task); + handle->reconnect_task = NULL; + } + GNUNET_assert (NULL == handle->request_head); + GNUNET_free (handle); +} + + +/** + * Cancel pending verify request + * + * @param lr the verify request to cancel + */ +void +GNUNET_ABD_request_cancel (struct GNUNET_ABD_Request *lr) +{ + struct GNUNET_ABD_Handle *handle = lr->abd_handle; + + GNUNET_CONTAINER_DLL_remove (handle->request_head, handle->request_tail, lr); + GNUNET_MQ_discard (lr->env); + GNUNET_free (lr); +} + + +/** + * Performs attribute collection. + * Collects all abds of subject to fulfill the + * attribute, if possible + * + * @param handle handle to the Credential service + * @param issuer_key the issuer public key + * @param issuer_attribute the issuer attribute + * @param subject_key the subject public key + * @param proc function to call on result + * @param proc_cls closure for processor + * @return handle to the queued request + */ +struct GNUNET_ABD_Request * +GNUNET_ABD_collect ( + struct GNUNET_ABD_Handle *handle, + const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key, + const char *issuer_attribute, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key, + enum GNUNET_ABD_AlgoDirectionFlags direction, + GNUNET_ABD_CredentialResultProcessor proc, + void *proc_cls, + GNUNET_ABD_IntermediateResultProcessor proc2, + void *proc2_cls) +{ + /* IPC to shorten abd names, return shorten_handle */ + struct CollectMessage *c_msg; + struct GNUNET_ABD_Request *vr; + size_t nlen; + + if (NULL == issuer_attribute) + { + GNUNET_break (0); + return NULL; + } + + //DEBUG LOG + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Trying to collect `%s' in ABD\n", + issuer_attribute); + nlen = strlen (issuer_attribute) + 1; + if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr)) + { + GNUNET_break (0); + return NULL; + } + vr = GNUNET_new (struct GNUNET_ABD_Request); + vr->abd_handle = handle; + vr->verify_proc = proc; + vr->proc_cls = proc_cls; + vr->int_proc = proc2; + vr->proc2_cls = proc2_cls; + vr->r_id = handle->r_id_gen++; + vr->env = + GNUNET_MQ_msg_extra (c_msg, nlen, GNUNET_MESSAGE_TYPE_ABD_COLLECT); + c_msg->id = htonl (vr->r_id); + c_msg->subject_key = *subject_key; + c_msg->issuer_key = *issuer_key; + c_msg->issuer_attribute_len = htons (strlen (issuer_attribute)); + c_msg->resolution_algo = htons (direction); + + GNUNET_memcpy (&c_msg[1], issuer_attribute, strlen (issuer_attribute)); + GNUNET_CONTAINER_DLL_insert (handle->request_head, handle->request_tail, vr); + if (NULL != handle->mq) + GNUNET_MQ_send_copy (handle->mq, vr->env); + return vr; +} +/** + * Performs attribute verification. + * Checks if there is a delegation chain from + * attribute ``issuer_attribute'' issued by the issuer + * with public key ``issuer_key'' maps to the attribute + * ``subject_attribute'' claimed by the subject with key + * ``subject_key'' + * + * @param handle handle to the Credential service + * @param issuer_key the issuer public key + * @param issuer_attribute the issuer attribute + * @param subject_key the subject public key + * @param delegate_count number of delegates provided + * @param delegates subject delegates + * @param proc function to call on result + * @param proc_cls closure for processor + * @return handle to the queued request + */ +struct GNUNET_ABD_Request * +GNUNET_ABD_verify ( + struct GNUNET_ABD_Handle *handle, + const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key, + const char *issuer_attribute, + const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key, + uint32_t delegate_count, + const struct GNUNET_ABD_Delegate *delegates, + enum GNUNET_ABD_AlgoDirectionFlags direction, + GNUNET_ABD_CredentialResultProcessor proc, + void *proc_cls, + GNUNET_ABD_IntermediateResultProcessor proc2, + void *proc2_cls) +{ + /* IPC to shorten abd names, return shorten_handle */ + struct VerifyMessage *v_msg; + struct GNUNET_ABD_Request *vr; + size_t nlen; + size_t clen; + + if (NULL == issuer_attribute || NULL == delegates) + { + GNUNET_break (0); + return NULL; + } + + clen = GNUNET_ABD_delegates_get_size (delegate_count, delegates); + + //DEBUG LOG + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Trying to verify `%s' in ABD\n", + issuer_attribute); + nlen = strlen (issuer_attribute) + 1 + clen; + if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr)) + { + GNUNET_break (0); + return NULL; + } + vr = GNUNET_new (struct GNUNET_ABD_Request); + vr->abd_handle = handle; + vr->verify_proc = proc; + vr->proc_cls = proc_cls; + vr->int_proc = proc2; + vr->proc2_cls = proc2_cls; + vr->r_id = handle->r_id_gen++; + vr->env = + GNUNET_MQ_msg_extra (v_msg, nlen, GNUNET_MESSAGE_TYPE_ABD_VERIFY); + v_msg->id = htonl (vr->r_id); + v_msg->subject_key = *subject_key; + v_msg->d_count = htonl (delegate_count); + v_msg->issuer_key = *issuer_key; + v_msg->issuer_attribute_len = htons (strlen (issuer_attribute)); + v_msg->resolution_algo = htons (direction); + + GNUNET_memcpy (&v_msg[1], issuer_attribute, strlen (issuer_attribute)); + GNUNET_ABD_delegates_serialize (delegate_count, + delegates, + clen, + ((char *) &v_msg[1]) + + strlen (issuer_attribute) + 1); + GNUNET_CONTAINER_DLL_insert (handle->request_head, handle->request_tail, vr); + if (NULL != handle->mq) + GNUNET_MQ_send_copy (handle->mq, vr->env); + return vr; +} + +/* end of abd_api.c */ diff --git a/src/abd/abd_serialization.c b/src/abd/abd_serialization.c new file mode 100644 index 000000000..d2bc15166 --- /dev/null +++ b/src/abd/abd_serialization.c @@ -0,0 +1,508 @@ +/* + This file is part of GNUnet. + Copyright (C) 2009-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 . + + SPDX-License-Identifier: AGPL3.0-or-later +*/ + + +/** + * @file abd/abd_serialization.c + * @brief API to serialize and deserialize delegation chains + * and abds + * @author Martin Schanzenbach + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_constants.h" +#include "gnunet_abd_service.h" +#include "gnunet_signatures.h" +#include "abd.h" + +/** + * Calculate how many bytes we will need to serialize + * the given delegation chain + * + * @param ds_count number of delegation chain entries + * @param dsr array of #GNUNET_ABD_DelegationSet + * @return the required size to serialize + */ +size_t +GNUNET_ABD_delegation_set_get_size ( + unsigned int ds_count, + const struct GNUNET_ABD_DelegationSet *dsr) +{ + unsigned int i; + size_t ret; + + ret = sizeof (struct DelegationRecordData) * (ds_count); + + for (i = 0; i < ds_count; i++) + { + GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret); + ret += dsr[i].subject_attribute_len; + } + return ret; +} + +/** + * Serizalize the given delegation chain entries and abd + * + * @param d_count number of delegation chain entries + * @param dsr array of #GNUNET_ABD_DelegationSet + * @param dest_size size of the destination + * @param dest where to store the result + * @return the size of the data, -1 on failure + */ +ssize_t +GNUNET_ABD_delegation_set_serialize ( + unsigned int d_count, + const struct GNUNET_ABD_DelegationSet *dsr, + size_t dest_size, + char *dest) +{ + struct DelegationRecordData rec; + unsigned int i; + size_t off; + + off = 0; + for (i = 0; i < d_count; i++) + { + rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len); + rec.subject_key = dsr[i].subject_key; + if (off + sizeof (rec) > dest_size) + return -1; + GNUNET_memcpy (&dest[off], &rec, sizeof (rec)); + off += sizeof (rec); + if (0 == dsr[i].subject_attribute_len) + continue; + if (off + dsr[i].subject_attribute_len > dest_size) + return -1; + GNUNET_memcpy (&dest[off], + dsr[i].subject_attribute, + dsr[i].subject_attribute_len); + off += dsr[i].subject_attribute_len; + } + return off; +} + + +/** + * Deserialize the given destination + * + * @param len size of the serialized delegation chain and cred + * @param src the serialized data + * @param d_count the number of delegation chain entries + * @param dsr where to put the delegation chain entries + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +int +GNUNET_ABD_delegation_set_deserialize ( + size_t len, + const char *src, + unsigned int d_count, + struct GNUNET_ABD_DelegationSet *dsr) +{ + struct DelegationRecordData rec; + unsigned int i; + size_t off; + + off = 0; + for (i = 0; i < d_count; i++) + { + if (off + sizeof (rec) > len) + return GNUNET_SYSERR; + GNUNET_memcpy (&rec, &src[off], sizeof (rec)); + dsr[i].subject_key = rec.subject_key; + off += sizeof (rec); + dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len); + if (off + dsr[i].subject_attribute_len > len) + return GNUNET_SYSERR; + dsr[i].subject_attribute = (char *) &src[off]; + off += dsr[i].subject_attribute_len; + } + return GNUNET_OK; +} + + +/** + * Calculate how many bytes we will need to serialize + * the abds + * + * @param c_count number of abd entries + * @param cd a #GNUNET_ABD_Credential + * @return the required size to serialize + */ +size_t +GNUNET_ABD_delegates_get_size ( + unsigned int c_count, + const struct GNUNET_ABD_Delegate *cd) +{ + unsigned int i; + size_t ret; + + ret = sizeof (struct DelegateEntry) * (c_count); + + for (i = 0; i < c_count; i++) + { + GNUNET_assert ((ret + cd[i].issuer_attribute_len + cd[i].subject_attribute_len) >= ret); + // subject_attribute_len should be 0 + ret += cd[i].issuer_attribute_len + cd[i].subject_attribute_len; + } + return ret; +} +/** + * Serizalize the given abds + * + * @param c_count number of abd entries + * @param cd a #GNUNET_ABD_Credential + * @param dest_size size of the destination + * @param dest where to store the result + * @return the size of the data, -1 on failure + */ +ssize_t +GNUNET_ABD_delegates_serialize ( + unsigned int c_count, + const struct GNUNET_ABD_Delegate *cd, + size_t dest_size, + char *dest) +{ + struct DelegateEntry c_rec; + unsigned int i; + size_t off; + + off = 0; + for (i = 0; i < c_count; i++) + { + //c_rec.subject_attribute_len = htonl ((uint32_t) cd[i].subject_attribute_len); + c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len); + c_rec.issuer_key = cd[i].issuer_key; + c_rec.subject_key = cd[i].subject_key; + c_rec.signature = cd[i].signature; + c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DELEGATE); + c_rec.purpose.size = + htonl ((sizeof (struct DelegateEntry) + cd[i].issuer_attribute_len) - + sizeof (struct GNUNET_CRYPTO_EcdsaSignature)); + c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us); + if (off + sizeof (c_rec) > dest_size) + return -1; + GNUNET_memcpy (&dest[off], &c_rec, sizeof (c_rec)); + off += sizeof (c_rec); + if (off + cd[i].issuer_attribute_len > dest_size) + return -1; + GNUNET_memcpy (&dest[off], + cd[i].issuer_attribute, + cd[i].issuer_attribute_len); + off += cd[i].issuer_attribute_len; + } + + return off; +} + + +/** + * Deserialize the given destination + * + * @param len size of the serialized creds + * @param src the serialized data + * @param c_count the number of abd entries + * @param cd where to put the abd data + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +int +GNUNET_ABD_delegates_deserialize (size_t len, + const char *src, + unsigned int c_count, + struct GNUNET_ABD_Delegate *cd) +{ + struct DelegateEntry c_rec; + unsigned int i; + size_t off; + + off = 0; + for (i = 0; i < c_count; i++) + { + if (off + sizeof (c_rec) > len) + return GNUNET_SYSERR; + GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec)); + cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len); + cd[i].issuer_key = c_rec.issuer_key; + cd[i].subject_key = c_rec.subject_key; + cd[i].signature = c_rec.signature; + cd[i].expiration.abs_value_us = GNUNET_ntohll (c_rec.expiration); + off += sizeof (c_rec); + if (off + cd[i].issuer_attribute_len > len) + return GNUNET_SYSERR; + cd[i].issuer_attribute = &src[off]; + off += cd[i].issuer_attribute_len; + cd[i].subject_attribute_len = 0; + } + return GNUNET_OK; +} + + +/** + * Calculate how many bytes we will need to serialize + * the given delegation chain and abd + * + * @param d_count number of delegation chain entries + * @param dd array of #GNUNET_ABD_Delegation + * @param c_count number of abd entries + * @param cd a #GNUNET_ABD_Credential + * @return the required size to serialize + */ +size_t +GNUNET_ABD_delegation_chain_get_size ( + unsigned int d_count, + const struct GNUNET_ABD_Delegation *dd, + unsigned int c_count, + const struct GNUNET_ABD_Delegate *cd) +{ + unsigned int i; + size_t ret; + + ret = sizeof (struct ChainEntry) * (d_count); + + for (i = 0; i < d_count; i++) + { + GNUNET_assert ( + (ret + dd[i].issuer_attribute_len + dd[i].subject_attribute_len) >= ret); + ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len; + } + return ret + GNUNET_ABD_delegates_get_size (c_count, cd); +} + +/** + * Serizalize the given delegation chain entries and abd + * + * @param d_count number of delegation chain entries + * @param dd array of #GNUNET_ABD_Delegation + * @param c_count number of abd entries + * @param cd a #GNUNET_ABD_Credential + * @param dest_size size of the destination + * @param dest where to store the result + * @return the size of the data, -1 on failure + */ +ssize_t +GNUNET_ABD_delegation_chain_serialize ( + unsigned int d_count, + const struct GNUNET_ABD_Delegation *dd, + unsigned int c_count, + const struct GNUNET_ABD_Delegate *cd, + size_t dest_size, + char *dest) +{ + struct ChainEntry rec; + unsigned int i; + size_t off; + + off = 0; + for (i = 0; i < d_count; i++) + { + rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len); + rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len); + rec.issuer_key = dd[i].issuer_key; + rec.subject_key = dd[i].subject_key; + if (off + sizeof (rec) > dest_size) + return -1; + GNUNET_memcpy (&dest[off], &rec, sizeof (rec)); + off += sizeof (rec); + if (off + dd[i].issuer_attribute_len > dest_size) + return -1; + GNUNET_memcpy (&dest[off], + dd[i].issuer_attribute, + dd[i].issuer_attribute_len); + off += dd[i].issuer_attribute_len; + if (0 == dd[i].subject_attribute_len) + continue; + if (off + dd[i].subject_attribute_len > dest_size) + return -1; + GNUNET_memcpy (&dest[off], + dd[i].subject_attribute, + dd[i].subject_attribute_len); + off += dd[i].subject_attribute_len; + } + return off + GNUNET_ABD_delegates_serialize (c_count, + cd, + dest_size - off, + &dest[off]); +} + + +/** + * Deserialize the given destination + * + * @param len size of the serialized delegation chain and cred + * @param src the serialized data + * @param d_count the number of delegation chain entries + * @param dd where to put the delegation chain entries + * @param c_count the number of abd entries + * @param cd where to put the abd data + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +int +GNUNET_ABD_delegation_chain_deserialize ( + size_t len, + const char *src, + unsigned int d_count, + struct GNUNET_ABD_Delegation *dd, + unsigned int c_count, + struct GNUNET_ABD_Delegate *cd) +{ + struct ChainEntry rec; + unsigned int i; + size_t off; + + off = 0; + for (i = 0; i < d_count; i++) + { + if (off + sizeof (rec) > len) + return GNUNET_SYSERR; + GNUNET_memcpy (&rec, &src[off], sizeof (rec)); + dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len); + dd[i].issuer_key = rec.issuer_key; + dd[i].subject_key = rec.subject_key; + off += sizeof (rec); + if (off + dd[i].issuer_attribute_len > len) + return GNUNET_SYSERR; + dd[i].issuer_attribute = &src[off]; + off += dd[i].issuer_attribute_len; + dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len); + if (off + dd[i].subject_attribute_len > len) + return GNUNET_SYSERR; + dd[i].subject_attribute = &src[off]; + off += dd[i].subject_attribute_len; + } + return GNUNET_ABD_delegates_deserialize (len - off, + &src[off], + c_count, + cd); +} + +int +GNUNET_ABD_delegate_serialize (struct GNUNET_ABD_Delegate *dele, + char **data) +{ + size_t size; + struct DelegateEntry *cdata; + int attr_len; + + // +1 for \0 + if (0 == dele->subject_attribute_len) + { + attr_len = dele->issuer_attribute_len + 1; + } + else + { + attr_len = dele->issuer_attribute_len + dele->subject_attribute_len + 2; + } + size = sizeof (struct DelegateEntry) + attr_len; + + char tmp_str[attr_len]; + GNUNET_memcpy (tmp_str, dele->issuer_attribute, dele->issuer_attribute_len); + if (0 != dele->subject_attribute_len) + { + tmp_str[dele->issuer_attribute_len] = '\0'; + GNUNET_memcpy (tmp_str + dele->issuer_attribute_len + 1, + dele->subject_attribute, + dele->subject_attribute_len); + } + tmp_str[attr_len - 1] = '\0'; + + *data = GNUNET_malloc (size); + cdata = (struct DelegateEntry *) *data; + cdata->subject_key = dele->subject_key; + cdata->issuer_key = dele->issuer_key; + cdata->expiration = GNUNET_htonll (dele->expiration.abs_value_us); + cdata->signature = dele->signature; + cdata->issuer_attribute_len = htonl (dele->issuer_attribute_len + 1); + if (0 == dele->subject_attribute_len) + { + cdata->subject_attribute_len = htonl (0); + } + else + { + cdata->subject_attribute_len = htonl (dele->subject_attribute_len + 1); + } + cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DELEGATE); + cdata->purpose.size = + htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature)); + + GNUNET_memcpy (&cdata[1], tmp_str, attr_len); + + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_DELEGATE, + &cdata->purpose, + &cdata->signature, + &cdata->issuer_key)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Serialize: Invalid delegate\n"); + return 0; + } + return size; +} + +struct GNUNET_ABD_Delegate * +GNUNET_ABD_delegate_deserialize (const char *data, size_t data_size) +{ + struct GNUNET_ABD_Delegate *dele; + struct DelegateEntry *cdata; + char *attr_combo_str; + + if (data_size < sizeof (struct DelegateEntry)) + return NULL; + cdata = (struct DelegateEntry *) data; + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_DELEGATE, + &cdata->purpose, + &cdata->signature, + &cdata->issuer_key)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Deserialize: Invalid delegate\n"); + return NULL; + } + attr_combo_str = (char *) &cdata[1]; + int iss_len = ntohl (cdata->issuer_attribute_len); + int sub_len = ntohl (cdata->subject_attribute_len); + int attr_combo_len = iss_len + sub_len; + + dele = + GNUNET_malloc (sizeof (struct GNUNET_ABD_Delegate) + attr_combo_len); + + dele->issuer_key = cdata->issuer_key; + dele->subject_key = cdata->subject_key; + GNUNET_memcpy (&dele[1], attr_combo_str, attr_combo_len); + dele->signature = cdata->signature; + + // Set the pointers for the attributes + dele->issuer_attribute = (char *) &dele[1]; + dele->issuer_attribute_len = iss_len; + dele->subject_attribute_len = sub_len; + if (0 == sub_len) + { + dele->subject_attribute = NULL; + } + else + { + dele->subject_attribute = (char *) &dele[1] + iss_len; + } + + dele->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration); + + return dele; +} + +/* end of abd_serialization.c */ diff --git a/src/abd/abd_serialization.h b/src/abd/abd_serialization.h new file mode 100644 index 000000000..cef9f42ef --- /dev/null +++ b/src/abd/abd_serialization.h @@ -0,0 +1,165 @@ +/* + This file is part of GNUnet. + Copyright (C) 2009-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 . + + SPDX-License-Identifier: AGPL3.0-or-later +*/ + + +/** + * @file abd/abd_serialization.h + * @brief API to serialize and deserialize delegation chains + * and abds + * @author Martin Schanzenbach + */ +#ifndef ABD_SERIALIZATION_H +#define ABD_SERIALIZATION_H + +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_constants.h" +#include "gnunet_abd_service.h" + +/** + * Calculate how many bytes we will need to serialize + * the given delegation record + * + * @param ds_count number of delegation chain entries + * @param dsr array of #GNUNET_ABD_Delegation + * @return the required size to serialize + */ +size_t +GNUNET_ABD_delegation_set_get_size ( + unsigned int ds_count, + const struct GNUNET_ABD_DelegationSet *dsr); + +/** + * Serizalize the given delegation record entries + * + * @param d_count number of delegation chain entries + * @param dsr array of #GNUNET_ABD_Delegation + * @param dest_size size of the destination + * @param dest where to store the result + * @return the size of the data, -1 on failure + */ +ssize_t +GNUNET_ABD_delegation_set_serialize ( + unsigned int d_count, + const struct GNUNET_ABD_DelegationSet *dsr, + size_t dest_size, + char *dest); + + +/** + * Deserialize the given destination + * + * @param len size of the serialized delegation recird + * @param src the serialized data + * @param d_count the number of delegation chain entries + * @param dsr where to put the delegation chain entries + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +int +GNUNET_ABD_delegation_set_deserialize ( + size_t len, + const char *src, + unsigned int d_count, + struct GNUNET_ABD_DelegationSet *dsr); + +/** + * Calculate how many bytes we will need to serialize + * the given delegation chain and abd + * + * @param d_count number of delegation chain entries + * @param dd array of #GNUNET_ABD_Delegation + * @param c_count number of abd entries + * @param cd a #GNUNET_ABD_Delegate + * @return the required size to serialize + */ +size_t +GNUNET_ABD_delegation_chain_get_size ( + unsigned int d_count, + const struct GNUNET_ABD_Delegation *dd, + unsigned int c_count, + const struct GNUNET_ABD_Delegate *cd); + +/** + * Serizalize the given delegation chain entries and abd + * + * @param d_count number of delegation chain entries + * @param dd array of #GNUNET_ABD_Delegation + * @param c_count number of abd entries + * @param cd a #GNUNET_ABD_Delegate + * @param dest_size size of the destination + * @param dest where to store the result + * @return the size of the data, -1 on failure + */ +ssize_t +GNUNET_ABD_delegation_chain_serialize ( + unsigned int d_count, + const struct GNUNET_ABD_Delegation *dd, + unsigned int c_count, + const struct GNUNET_ABD_Delegate *cd, + size_t dest_size, + char *dest); + + +/** + * Deserialize the given destination + * + * @param len size of the serialized delegation chain and cred + * @param src the serialized data + * @param d_count the number of delegation chain entries + * @param dd where to put the delegation chain entries + * @param c_count number of abd entries + * @param cd where to put the abd data + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +int +GNUNET_ABD_delegation_chain_deserialize ( + size_t len, + const char *src, + unsigned int d_count, + struct GNUNET_ABD_Delegation *dd, + unsigned int c_count, + struct GNUNET_ABD_Delegate *cd); +size_t +GNUNET_ABD_delegates_get_size ( + unsigned int c_count, + const struct GNUNET_ABD_Delegate *cd); + +ssize_t +GNUNET_ABD_delegates_serialize ( + unsigned int c_count, + const struct GNUNET_ABD_Delegate *cd, + size_t dest_size, + char *dest); + + +int +GNUNET_ABD_delegates_deserialize (size_t len, + const char *src, + unsigned int c_count, + struct GNUNET_ABD_Delegate *cd); + +int +GNUNET_ABD_delegate_serialize (struct GNUNET_ABD_Delegate *cred, + char **data); + +struct GNUNET_ABD_Delegate * +GNUNET_ABD_delegate_deserialize (const char *data, size_t data_size); +#endif +/* end of abd_serialization.h */ diff --git a/src/abd/delegate_misc.c b/src/abd/delegate_misc.c new file mode 100644 index 000000000..ecc7f7669 --- /dev/null +++ b/src/abd/delegate_misc.c @@ -0,0 +1,274 @@ +/* + This file is part of GNUnet. + Copyright (C) 2009-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 . + + SPDX-License-Identifier: AGPL3.0-or-later +*/ + + +/** + * @file abd/delegate_misc.c + * @brief Misc API for delegate + * + * @author Martin Schanzenbach + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_constants.h" +#include "gnunet_abd_service.h" +#include "gnunet_signatures.h" +#include "abd.h" +#include + +char * +GNUNET_ABD_delegate_to_string ( + const struct GNUNET_ABD_Delegate *cred) +{ + char *cred_str; + char *subject_pkey; + char *issuer_pkey; + char *signature; + + subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key); + issuer_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key); + GNUNET_STRINGS_base64_encode ((char *) &cred->signature, + sizeof (struct GNUNET_CRYPTO_EcdsaSignature), + &signature); + if (0 == cred->subject_attribute_len) + { + GNUNET_asprintf (&cred_str, + "%s.%s -> %s | %s | %" SCNu64, + issuer_pkey, + cred->issuer_attribute, + subject_pkey, + signature, + cred->expiration.abs_value_us); + } + else + { + GNUNET_asprintf (&cred_str, + "%s.%s -> %s.%s | %s | %" SCNu64, + issuer_pkey, + cred->issuer_attribute, + subject_pkey, + cred->subject_attribute, + signature, + cred->expiration.abs_value_us); + } + GNUNET_free (subject_pkey); + GNUNET_free (issuer_pkey); + GNUNET_free (signature); + + return cred_str; +} + +struct GNUNET_ABD_Delegate * +GNUNET_ABD_delegate_from_string (const char *s) +{ + struct GNUNET_ABD_Delegate *dele; + size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8; + if (enclen % 5 > 0) + enclen += 5 - enclen % 5; + enclen /= 5; /* 260/5 = 52 */ + char subject_pkey[enclen + 1]; + char issuer_pkey[enclen + 1]; + char iss_attr[253 + 1]; + // Needs to be initialized, in case of Type 1 credential (A.a <- B) + char sub_attr[253 + 1] = ""; + char signature[256]; //TODO max payload size + + struct GNUNET_CRYPTO_EcdsaSignature *sig; + struct GNUNET_TIME_Absolute etime_abs; + + // If it's A.a <- B.b... + if (6 != SSCANF (s, + "%52s.%253s -> %52s.%253s | %s | %" SCNu64, + issuer_pkey, + iss_attr, + subject_pkey, + sub_attr, + signature, + &etime_abs.abs_value_us)) + { + // Try if it's A.a <- B + if (5 != SSCANF (s, + "%52s.%253s -> %52s | %s | %" SCNu64, + issuer_pkey, + iss_attr, + subject_pkey, + signature, + &etime_abs.abs_value_us)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to parse DEL record string `%s'\n", + s); + return NULL; + } + } + + // +1 for \0 + int attr_len; + if (strcmp (sub_attr, "") == 0) + { + attr_len = strlen (iss_attr) + 1; + } + else + { + attr_len = strlen (iss_attr) + strlen (sub_attr) + 2; + } + dele = GNUNET_malloc (sizeof (struct GNUNET_ABD_Delegate) + attr_len); + + char tmp_str[attr_len]; + GNUNET_memcpy (tmp_str, iss_attr, strlen (iss_attr)); + if (strcmp (sub_attr, "") != 0) + { + tmp_str[strlen (iss_attr)] = '\0'; + GNUNET_memcpy (tmp_str + strlen (iss_attr) + 1, + sub_attr, + strlen (sub_attr)); + } + tmp_str[attr_len - 1] = '\0'; + + GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey, + strlen (subject_pkey), + &dele->subject_key); + GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_pkey, + strlen (issuer_pkey), + &dele->issuer_key); + GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdsaSignature) == + GNUNET_STRINGS_base64_decode (signature, + strlen (signature), + (void **) &sig)); + dele->signature = *sig; + dele->expiration = etime_abs; + GNUNET_free (sig); + + GNUNET_memcpy (&dele[1], tmp_str, attr_len); + + dele->issuer_attribute = (char *) &dele[1]; + dele->issuer_attribute_len = strlen (iss_attr); + if (strcmp (sub_attr, "") == 0) + { + dele->subject_attribute = NULL; + dele->subject_attribute_len = 0; + } + else + { + dele->subject_attribute = (char *) &dele[1] + strlen (iss_attr) + 1; + dele->subject_attribute_len = strlen (sub_attr); + } + + return dele; +} + +/** + * Issue an attribute to a subject + * + * @param issuer the ego that should be used to issue the attribute + * @param subject the subject of the attribute + * @param iss_attr the name of the attribute + * @return handle to the queued request + */ + +struct GNUNET_ABD_Delegate * +GNUNET_ABD_delegate_issue ( + const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, + struct GNUNET_CRYPTO_EcdsaPublicKey *subject, + const char *iss_attr, + const char *sub_attr, + struct GNUNET_TIME_Absolute *expiration) +{ + struct DelegateEntry *del; + struct GNUNET_ABD_Delegate *dele; + size_t size; + int attr_len; + + if (NULL == sub_attr) + { + // +1 for \0 + attr_len = strlen (iss_attr) + 1; + } + else + { + // +2 for both strings need to be terminated with \0 + attr_len = strlen (iss_attr) + strlen (sub_attr) + 2; + } + size = sizeof (struct DelegateEntry) + attr_len; + + char tmp_str[attr_len]; + GNUNET_memcpy (tmp_str, iss_attr, strlen (iss_attr)); + if (NULL != sub_attr) + { + tmp_str[strlen (iss_attr)] = '\0'; + GNUNET_memcpy (tmp_str + strlen (iss_attr) + 1, + sub_attr, + strlen (sub_attr)); + } + tmp_str[attr_len - 1] = '\0'; + + del = GNUNET_malloc (size); + del->purpose.size = + htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature)); + del->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DELEGATE); + GNUNET_CRYPTO_ecdsa_key_get_public (issuer, &del->issuer_key); + del->subject_key = *subject; + del->expiration = GNUNET_htonll (expiration->abs_value_us); + del->issuer_attribute_len = htonl (strlen (iss_attr) + 1); + if (NULL == sub_attr) + { + del->subject_attribute_len = htonl (0); + } + else + { + del->subject_attribute_len = htonl (strlen (sub_attr) + 1); + } + + GNUNET_memcpy (&del[1], tmp_str, attr_len); + + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_sign (issuer, &del->purpose, &del->signature)) + { + GNUNET_break (0); + GNUNET_free (del); + return NULL; + } + + dele = GNUNET_malloc (sizeof (struct GNUNET_ABD_Delegate) + attr_len); + dele->signature = del->signature; + dele->expiration = *expiration; + GNUNET_CRYPTO_ecdsa_key_get_public (issuer, &dele->issuer_key); + + dele->subject_key = *subject; + + // Copy the combined string at the part in the memory where the struct ends + GNUNET_memcpy (&dele[1], tmp_str, attr_len); + + dele->issuer_attribute = (char *) &dele[1]; + dele->issuer_attribute_len = strlen (iss_attr); + if (NULL == sub_attr) + { + dele->subject_attribute = NULL; + dele->subject_attribute_len = 0; + } + else + { + dele->subject_attribute = (char *) &dele[1] + strlen (iss_attr) + 1; + dele->subject_attribute_len = strlen (sub_attr); + } + + GNUNET_free (del); + return dele; +} diff --git a/src/abd/delegate_misc.h b/src/abd/delegate_misc.h new file mode 100644 index 000000000..42a95ce99 --- /dev/null +++ b/src/abd/delegate_misc.h @@ -0,0 +1,36 @@ +/* + This file is part of GNUnet + Copyright (C) 2012-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 . + + SPDX-License-Identifier: AGPL3.0-or-later + */ +/** + * @file abd/delegate_misc.h + * @brief Delegate helper functions + */ +#ifndef DELEGATE_MISC_H +#define DELEGATE_MISC_H + +#include "gnunet_abd_service.h" + +char * +GNUNET_ABD_delegate_to_string ( + const struct GNUNET_ABD_Delegate *cred); + +struct GNUNET_ABD_Delegate * +GNUNET_ABD_delegate_from_string (const char *str); + +#endif diff --git a/src/abd/gnunet-abd.c b/src/abd/gnunet-abd.c new file mode 100644 index 000000000..23083ec68 --- /dev/null +++ b/src/abd/gnunet-abd.c @@ -0,0 +1,1070 @@ +/* + This file is part of GNUnet. + Copyright (C) 2012-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 . + + SPDX-License-Identifier: AGPL3.0-or-later +*/ +/** + * @file gnunet-abd.c + * @brief command line tool to access command line Credential service + * @author Martin Schanzenbach + */ +#include "platform.h" +#include +#include +#include +#include +#include "delegate_misc.h" +#include "abd_serialization.h" + +/** + * Configuration we are using. + */ +static const struct GNUNET_CONFIGURATION_Handle *cfg; + +/** + * Handle to the namestore. + */ +static struct GNUNET_NAMESTORE_Handle *ns; + +/** + * Private key for the our zone. + */ +static struct GNUNET_CRYPTO_EcdsaPrivateKey zone_pkey; + +/** + * EgoLookup + */ +static struct GNUNET_IDENTITY_EgoLookup *el; + +/** + * Handle to Credential service. + */ +static struct GNUNET_ABD_Handle *abd; + +/** + * Desired timeout for the lookup (default is no timeout). + */ +static struct GNUNET_TIME_Relative timeout; + +/** + * Handle to verify request + */ +static struct GNUNET_ABD_Request *verify_request; + +/** + * Handle to collect request + */ +static struct GNUNET_ABD_Request *collect_request; + +/** + * Task scheduled to handle timeout. + */ +static struct GNUNET_SCHEDULER_Task *tt; + +/** + * Return value of the commandline. + */ +static int ret = 0; + +/** + * Subject pubkey string + */ +static char *subject; + +/** + * Subject delegate string + */ +static char *subject_delegate; + +/** + * Credential TTL + */ +static char *expiration; + +/** + * Subject key + */ +struct GNUNET_CRYPTO_EcdsaPublicKey subject_pkey; + +/** + * Issuer key + */ +struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey; + + +/** + * Issuer pubkey string + */ +static char *issuer_key; + +/** + * ego + */ +static char *ego_name; + +/** + * Issuer attribute + */ +static char *issuer_attr; + +/** + * Verify mode + */ +static int verify; + +/** + * Collect mode + */ +static int collect; + +/** + * Create mode + */ +static int create_is; + +/** + * Create mode + */ +static int create_ss; + +/** + * Create mode + */ +static int sign_ss; + +/** + * Signed issue credentials + */ +static char *import; + +/** + * Is record private + */ +static int is_private; + +/** + * Search direction: forward + */ +static int forward; + +/** + * Search direction: backward + */ +static int backward; + +/** + * API enum, filled and passed for collect/verify + */ +enum GNUNET_ABD_AlgoDirectionFlags direction = 0; + +/** + * Queue entry for the 'add' operation. + */ +static struct GNUNET_NAMESTORE_QueueEntry *add_qe; + +/** + * Value in binary format. + */ +static void *data; + +/** + * Number of bytes in #data. + */ +static size_t data_size; + +/** + * Type string converted to DNS type value. + */ +static uint32_t type; + +/** + * Type of the record to add/remove, NULL to remove all. + */ +static char *typestring; +/** + * Expiration string converted to numeric value. + */ +static uint64_t etime; + +/** + * Is expiration time relative or absolute time? + */ +static int etime_is_rel = GNUNET_SYSERR; + +/** + * Fixed size of the public/private keys + */ +static const int key_length = 52; + +/** + * Record label for storing delegations + */ +static char *record_label; + +/** + * Task run on shutdown. Cleans up everything. + * + * @param cls unused + */ +static void +do_shutdown (void *cls) +{ + if (NULL != verify_request) + { + GNUNET_ABD_request_cancel (verify_request); + verify_request = NULL; + } + if (NULL != abd) + { + GNUNET_ABD_disconnect (abd); + abd = NULL; + } + if (NULL != tt) + { + GNUNET_SCHEDULER_cancel (tt); + tt = NULL; + } + if (NULL != el) + { + GNUNET_IDENTITY_ego_lookup_cancel (el); + el = NULL; + } + if (NULL != add_qe) + { + GNUNET_NAMESTORE_cancel (add_qe); + add_qe = NULL; + } + if (NULL != ns) + { + GNUNET_NAMESTORE_disconnect (ns); + ns = NULL; + } +} + + +/** + * Task run on timeout. Triggers shutdown. + * + * @param cls unused + */ +static void +do_timeout (void *cls) +{ + tt = NULL; + GNUNET_SCHEDULER_shutdown (); +} + +static void +handle_intermediate_result(void *cls, + struct GNUNET_ABD_Delegation *dd, + bool is_bw) +{ + char *prefix = ""; + if(is_bw) + prefix = "Backward -"; + else + prefix = "Forward -"; + + printf ("%s Intermediate result: %s.%s <- %s.%s\n", + prefix, + GNUNET_CRYPTO_ecdsa_public_key_to_string (&dd->issuer_key), + dd->issuer_attribute, + GNUNET_CRYPTO_ecdsa_public_key_to_string (&dd->subject_key), + dd->subject_attribute); +} + +static void +handle_collect_result (void *cls, + unsigned int d_count, + struct GNUNET_ABD_Delegation *dc, + unsigned int c_count, + struct GNUNET_ABD_Delegate *dele) +{ + int i; + char *line; + + verify_request = NULL; + if (NULL != dele) + { + for (i = 0; i < c_count; i++) + { + line = GNUNET_ABD_delegate_to_string (&dele[i]); + printf ("%s\n", line); + GNUNET_free (line); + } + } + else + { + printf ("Received NULL\n"); + } + + GNUNET_SCHEDULER_shutdown (); +} + + +static void +handle_verify_result (void *cls, + unsigned int d_count, + struct GNUNET_ABD_Delegation *dc, + unsigned int c_count, + struct GNUNET_ABD_Delegate *dele) +{ + int i; + char *iss_key; + char *sub_key; + + verify_request = NULL; + if (NULL == dele) + ret = 1; + else + { + printf ("Delegation Chain:\n"); + for (i = 0; i < d_count; i++) + { + iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].issuer_key); + sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].subject_key); + + if (0 != dc[i].subject_attribute_len) + { + printf ("(%d) %s.%s <- %s.%s\n", + i, + iss_key, + dc[i].issuer_attribute, + sub_key, + dc[i].subject_attribute); + } + else + { + printf ("(%d) %s.%s <- %s\n", + i, + iss_key, + dc[i].issuer_attribute, + sub_key); + } + GNUNET_free (iss_key); + GNUNET_free (sub_key); + } + printf ("\nDelegate(s):\n"); + for (i = 0; i < c_count; i++) + { + iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dele[i].issuer_key); + sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dele[i].subject_key); + printf ("%s.%s <- %s\n", iss_key, dele[i].issuer_attribute, sub_key); + GNUNET_free (iss_key); + GNUNET_free (sub_key); + } + printf ("Successful.\n"); + } + + GNUNET_SCHEDULER_shutdown (); +} + +/** + * Callback invoked from identity service with ego information. + * An @a ego of NULL means the ego was not found. + * + * @param cls closure with the configuration + * @param ego an ego known to identity service, or NULL + */ +static void +identity_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) +{ + const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; + + el = NULL; + if (NULL == ego) + { + if (NULL != ego_name) + { + fprintf (stderr, + _ ("Ego `%s' not known to identity service\n"), + ego_name); + } + GNUNET_SCHEDULER_shutdown (); + return; + } + + if (GNUNET_YES == collect) + { + + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key, + strlen (issuer_key), + &issuer_pkey)) + { + fprintf (stderr, + _ ("Issuer public key `%s' is not well-formed\n"), + issuer_key); + GNUNET_SCHEDULER_shutdown (); + } + privkey = GNUNET_IDENTITY_ego_get_private_key (ego); + + collect_request = GNUNET_ABD_collect (abd, + &issuer_pkey, + issuer_attr, + privkey, + direction, + &handle_collect_result, + NULL, + &handle_intermediate_result, + NULL); + return; + } + GNUNET_SCHEDULER_shutdown (); +} + +/** + * Parse expiration time. + * + * @param expirationstring text to parse + * @param etime_is_rel[out] set to #GNUNET_YES if time is relative + * @param etime[out] set to expiration time (abs or rel) + * @return #GNUNET_OK on success + */ +static int +parse_expiration (const char *expirationstring, + int *etime_is_rel, + uint64_t *etime) +{ + // copied from namestore/gnunet-namestore.c + struct GNUNET_TIME_Relative etime_rel; + struct GNUNET_TIME_Absolute etime_abs; + + if (0 == strcmp (expirationstring, "never")) + { + *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; + *etime_is_rel = GNUNET_NO; + return GNUNET_OK; + } + if (GNUNET_OK == + GNUNET_STRINGS_fancy_time_to_relative (expirationstring, &etime_rel)) + { + *etime_is_rel = GNUNET_YES; + *etime = etime_rel.rel_value_us; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Storing record with relative expiration time of %s\n", + GNUNET_STRINGS_relative_time_to_string (etime_rel, GNUNET_NO)); + return GNUNET_OK; + } + if (GNUNET_OK == + GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, &etime_abs)) + { + *etime_is_rel = GNUNET_NO; + *etime = etime_abs.abs_value_us; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Storing record with absolute expiration time of %s\n", + GNUNET_STRINGS_absolute_time_to_string (etime_abs)); + return GNUNET_OK; + } + return GNUNET_SYSERR; +} + +/** + * Function called if lookup fails. + */ +static void +error_cb (void *cls) +{ + fprintf (stderr, "Error occured during lookup, shutting down.\n"); + GNUNET_SCHEDULER_shutdown (); + return; +} +static void +add_continuation (void *cls, int32_t success, const char *emsg) +{ + struct GNUNET_NAMESTORE_QueueEntry **qe = cls; + *qe = NULL; + + if(GNUNET_OK == success) + printf ("Adding successful.\n"); + else + fprintf (stderr, "Error occured during adding, shutting down.\n"); + + GNUNET_SCHEDULER_shutdown (); +} + +static void +get_existing_record (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, + const char *rec_name, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct GNUNET_GNSRECORD_Data rdn[rd_count + 1]; + struct GNUNET_GNSRECORD_Data *rde; + + memset (rdn, 0, sizeof (struct GNUNET_GNSRECORD_Data)); + GNUNET_memcpy (&rdn[1], rd, rd_count * sizeof (struct GNUNET_GNSRECORD_Data)); + rde = &rdn[0]; + rde->data = data; + rde->data_size = data_size; + rde->record_type = type; + + // Set flags + if (GNUNET_YES == is_private) + rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; + rde->expiration_time = etime; + if (GNUNET_YES == etime_is_rel) + rde->flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; + else if (GNUNET_NO != etime_is_rel) + rde->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; + + GNUNET_assert (NULL != rec_name); + add_qe = GNUNET_NAMESTORE_records_store (ns, + &zone_pkey, + rec_name, + rd_count + 1, + rde, + &add_continuation, + &add_qe); + + return; +} + +static void +store_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) +{ + const struct GNUNET_CONFIGURATION_Handle *cfg = cls; + + el = NULL; + + ns = GNUNET_NAMESTORE_connect (cfg); + if (NULL == ns) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _ ("Failed to connect to namestore\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + + // Key handling + zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); + + if (GNUNET_GNSRECORD_TYPE_DELEGATE == type) + { + // Parse import + struct GNUNET_ABD_Delegate *cred; + cred = GNUNET_ABD_delegate_from_string (import); + + // Get import subject public key string + char *subject_pubkey_str = + GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key); + + // Get zone public key string + struct GNUNET_CRYPTO_EcdsaPublicKey zone_pubkey; + GNUNET_IDENTITY_ego_get_public_key (ego, &zone_pubkey); + char *zone_pubkey_str = + GNUNET_CRYPTO_ecdsa_public_key_to_string (&zone_pubkey); + + // Check if the subject key in the signed import matches the zone's key it is issued to + if (strcmp (zone_pubkey_str, subject_pubkey_str) != 0) + { + fprintf (stderr, + "Import signed delegate does not match this ego's public key.\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + + // Expiration + etime = cred->expiration.abs_value_us; + etime_is_rel = GNUNET_NO; + + // Prepare the data to be store in the record + data_size = GNUNET_ABD_delegate_serialize (cred, (char **) &data); + GNUNET_free (cred); + } + else + { + // For all other types e.g. GNUNET_GNSRECORD_TYPE_ATTRIBUTE + if (GNUNET_OK != + GNUNET_GNSRECORD_string_to_value (type, subject, &data, &data_size)) + { + fprintf (stderr, + "Value `%s' invalid for record type `%s'\n", + subject, + typestring); + GNUNET_SCHEDULER_shutdown (); + return; + } + + // Take care of expiration + if (NULL == expiration) + { + fprintf (stderr, "Missing option -e for operation 'create'\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (GNUNET_OK != parse_expiration (expiration, &etime_is_rel, &etime)) + { + fprintf (stderr, "Invalid time format `%s'\n", expiration); + GNUNET_SCHEDULER_shutdown (); + return; + } + } + + // Start lookup + add_qe = GNUNET_NAMESTORE_records_lookup (ns, + &zone_pkey, + record_label, + &error_cb, + NULL, + &get_existing_record, + NULL); + return; +} + +static void +sign_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) +{ + const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; + struct GNUNET_ABD_Delegate *dele; + struct GNUNET_TIME_Absolute etime_abs; + char *res; + + el = NULL; + + // work on expiration time + if (NULL == expiration) + { + fprintf (stderr, "Please specify a TTL\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + else if (GNUNET_OK != + GNUNET_STRINGS_fancy_time_to_absolute (expiration, &etime_abs)) + { + fprintf (stderr, + "%s is not a valid ttl! Only absolute times are accepted!\n", + expiration); + GNUNET_SCHEDULER_shutdown (); + return; + } + + // If contains a space - split it by the first space only - assume first entry is subject followed by attribute(s) + char *subject_pubkey_str; + char *subject_attr = NULL; + char *token; + + // Subject Public Key + token = strtok (subject, " "); + if (key_length == strlen (token)) + { + subject_pubkey_str = token; + } + else + { + fprintf (stderr, "Key error, wrong length: %ld!\n", strlen (token)); + GNUNET_SCHEDULER_shutdown (); + return; + } + // Subject Attribute(s) + token = strtok (NULL, " "); + if (NULL != token) + { + subject_attr = token; + } + + // work on keys + privkey = GNUNET_IDENTITY_ego_get_private_key (ego); + + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pubkey_str, + strlen (subject_pubkey_str), + &subject_pkey)) + { + fprintf (stderr, + "Subject public key `%s' is not well-formed\n", + subject_pubkey_str); + GNUNET_SCHEDULER_shutdown (); + return; + } + + // Sign delegate + dele = GNUNET_ABD_delegate_issue (privkey, + &subject_pkey, + issuer_attr, + subject_attr, + &etime_abs); + res = GNUNET_ABD_delegate_to_string (dele); + GNUNET_free (dele); + printf ("%s\n", res); + + GNUNET_free_non_null (ego_name); + ego_name = NULL; + + GNUNET_SCHEDULER_shutdown (); +} + +/** + * Main function that will be run. + * + * @param cls closure + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param c configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *c) +{ + cfg = c; + + tt = GNUNET_SCHEDULER_add_delayed (timeout, &do_timeout, NULL); + GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); + + // Check relevant cmdline parameters + if (GNUNET_YES == create_is) + { + if (NULL == ego_name) + { + fprintf (stderr, "Missing option '-ego'\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (NULL == issuer_attr) + { + fprintf (stderr, "Missing option '-attribute' for issuer attribute\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (NULL == subject) + { + fprintf (stderr, "Missing option -subject for operation 'create'.'\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + + // Lookup ego, on success call store_cb and store as ATTRIBUTE type + type = GNUNET_GNSRECORD_TYPE_ATTRIBUTE; + record_label = issuer_attr; + el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &store_cb, (void *) cfg); + return; + } + + if (GNUNET_YES == create_ss) + { + + // check if signed parameter has been passed in cmd line call + if (NULL == import) + { + fprintf (stderr, "'import' required\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + + type = GNUNET_GNSRECORD_TYPE_DELEGATE; + record_label = GNUNET_GNS_EMPTY_LABEL_AT; + // Store subject side + el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &store_cb, (void *) cfg); + + return; + } + + if (GNUNET_YES == sign_ss) + { + if (NULL == ego_name) + { + fprintf (stderr, "ego required\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (NULL == subject) + { + fprintf (stderr, "Subject public key needed\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + + // lookup ego and call function sign_cb on success + el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &sign_cb, (void *) cfg); + return; + } + + if (GNUNET_NO == forward && GNUNET_NO == backward) + { + // set default: bidirectional + forward = GNUNET_YES; + backward = GNUNET_YES; + } + if (GNUNET_YES == forward) + direction |= GNUNET_ABD_FLAG_FORWARD; + if (GNUNET_YES == backward) + direction |= GNUNET_ABD_FLAG_BACKWARD; + + if (GNUNET_YES == collect) + { + if (NULL == issuer_key) + { + fprintf (stderr, _ ("Issuer public key not well-formed\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + + abd = GNUNET_ABD_connect (cfg); + + if (NULL == abd) + { + fprintf (stderr, _ ("Failed to connect to ABD\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (NULL == issuer_attr) + { + fprintf (stderr, _ ("You must provide issuer the attribute\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + + if (NULL == ego_name) + { + fprintf (stderr, _ ("ego required\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &identity_cb, (void *) cfg); + return; + } + + if (NULL == subject) + { + fprintf (stderr, _ ("Subject public key needed\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (subject, + strlen (subject), + &subject_pkey)) + { + fprintf (stderr, + _ ("Subject public key `%s' is not well-formed\n"), + subject); + GNUNET_SCHEDULER_shutdown (); + return; + } + + if (GNUNET_YES == verify) + { + if (NULL == issuer_key) + { + fprintf (stderr, _ ("Issuer public key not well-formed\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key, + strlen (issuer_key), + &issuer_pkey)) + { + fprintf (stderr, + _ ("Issuer public key `%s' is not well-formed\n"), + issuer_key); + GNUNET_SCHEDULER_shutdown (); + return; + } + abd = GNUNET_ABD_connect (cfg); + + if (NULL == abd) + { + fprintf (stderr, _ ("Failed to connect to ABD\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (NULL == issuer_attr || NULL == subject_delegate) + { + fprintf (stderr, _ ("You must provide issuer and subject attributes\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + + //Subject credentials are comma separated + char *tmp = GNUNET_strdup (subject_delegate); + char *tok = strtok (tmp, ","); + if (NULL == tok) + { + fprintf (stderr, "Invalid subject credentials\n"); + GNUNET_free (tmp); + GNUNET_SCHEDULER_shutdown (); + return; + } + int count = 1; + int i; + while (NULL != (tok = strtok (NULL, ","))) + count++; + struct GNUNET_ABD_Delegate delegates[count]; + struct GNUNET_ABD_Delegate *dele; + GNUNET_free (tmp); + tmp = GNUNET_strdup (subject_delegate); + tok = strtok (tmp, ","); + for (i = 0; i < count; i++) + { + dele = GNUNET_ABD_delegate_from_string (tok); + GNUNET_memcpy (&delegates[i], + dele, + sizeof (struct GNUNET_ABD_Delegate)); + delegates[i].issuer_attribute = GNUNET_strdup (dele->issuer_attribute); + tok = strtok (NULL, ","); + GNUNET_free (dele); + } + + verify_request = GNUNET_ABD_verify (abd, + &issuer_pkey, + issuer_attr, + &subject_pkey, + count, + delegates, + direction, + &handle_verify_result, + NULL, + &handle_intermediate_result, + NULL); + for (i = 0; i < count; i++) + { + GNUNET_free ((char *) delegates[i].issuer_attribute); + } + GNUNET_free (tmp); + } + else + { + fprintf (stderr, + _ ( + "Please specify name to lookup, subject key and issuer key!\n")); + GNUNET_SCHEDULER_shutdown (); + } + return; +} + + +/** + * The main function for gnunet-gns. + * + * @param argc number of arguments from the command line + * @param argv command line arguments + * @return 0 ok, 1 on error + */ +int +main (int argc, char *const *argv) +{ + struct GNUNET_GETOPT_CommandLineOption options[] = + {GNUNET_GETOPT_option_flag ('V', + "verify", + gettext_noop ( + "verify credential against attribute"), + &verify), + GNUNET_GETOPT_option_string ( + 's', + "subject", + "PKEY", + gettext_noop ( + "The public key of the subject to lookup the" + "credential for, or for issuer side storage: subject and its attributes"), + &subject), + GNUNET_GETOPT_option_string ( + 'd', + "delegate", + "DELE", + gettext_noop ("The private, signed delegate presented by the subject"), + &subject_delegate), + GNUNET_GETOPT_option_string ( + 'i', + "issuer", + "PKEY", + gettext_noop ( + "The public key of the authority to verify the credential against"), + &issuer_key), + GNUNET_GETOPT_option_string ('e', + "ego", + "EGO", + gettext_noop ("The ego/zone name to use"), + &ego_name), + GNUNET_GETOPT_option_string ( + 'a', + "attribute", + "ATTR", + gettext_noop ("The issuer attribute to verify against or to issue"), + &issuer_attr), + GNUNET_GETOPT_option_string ('T', + "ttl", + "EXP", + gettext_noop ( + "The time to live for the credential." + "e.g. 5m, 6h, \"1990-12-30 12:00:00\""), + &expiration), + GNUNET_GETOPT_option_flag ('g', + "collect", + gettext_noop ("collect credentials"), + &collect), + GNUNET_GETOPT_option_flag ('U', + "createIssuerSide", + gettext_noop ( + "Create and issue a credential issuer side."), + &create_is), + GNUNET_GETOPT_option_flag ('C', + "createSubjectSide", + gettext_noop ( + "Issue a credential subject side."), + &create_ss), + GNUNET_GETOPT_option_flag ( + 'S', + "signSubjectSide", + gettext_noop ("Create, sign and return a credential subject side."), + &sign_ss), + GNUNET_GETOPT_option_string ( + 'x', + "import", + "IMP", + gettext_noop ( + "Import signed credentials that should be issued to a zone/ego"), + &import), + GNUNET_GETOPT_option_flag ('P', + "private", + gettext_noop ("Create private record entry."), + &is_private), + GNUNET_GETOPT_option_flag ( + 'F', + "forward", + gettext_noop ( + "Indicates that the collect/verify process is done via forward search."), + &forward), + GNUNET_GETOPT_option_flag ( + 'B', + "backward", + gettext_noop ( + "Indicates that the collect/verify process is done via forward search."), + &backward), + GNUNET_GETOPT_OPTION_END}; + + + timeout = GNUNET_TIME_UNIT_FOREVER_REL; + if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) + return 2; + + GNUNET_log_setup ("gnunet-abd", "WARNING", NULL); + if (GNUNET_OK != GNUNET_PROGRAM_run (argc, + argv, + "gnunet-abd", + _ ("GNUnet abd resolver tool"), + options, + &run, + NULL)) + ret = 1; + GNUNET_free ((void *) argv); + return ret; +} + +/* end of gnunet-abd.c */ diff --git a/src/abd/gnunet-service-abd.c b/src/abd/gnunet-service-abd.c new file mode 100644 index 000000000..84222b290 --- /dev/null +++ b/src/abd/gnunet-service-abd.c @@ -0,0 +1,1751 @@ +/* + This file is part of GNUnet. + Copyright (C) 2011-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 . + + SPDX-License-Identifier: AGPL3.0-or-later +*/ +/** + * @file abd/gnunet-service-abd.c + * @brief GNUnet Credential Service (main service) + * @author Martin Schanzenbach + */ +#include "platform.h" + +#include "gnunet_util_lib.h" + +#include "abd.h" +#include "abd_serialization.h" +#include "gnunet_abd_service.h" +#include "gnunet_protocols.h" +#include "gnunet_signatures.h" +#include "gnunet_statistics_service.h" +#include +#include +#include +#include +#include + + +#define GNUNET_ABD_MAX_LENGTH 255 + +struct VerifyRequestHandle; + +struct DelegationSetQueueEntry; + + +struct DelegationChainEntry +{ + /** + * DLL + */ + struct DelegationChainEntry *next; + + /** + * DLL + */ + struct DelegationChainEntry *prev; + + /** + * The issuer + */ + struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key; + + /** + * The subject + */ + struct GNUNET_CRYPTO_EcdsaPublicKey subject_key; + + /** + * The issued attribute + */ + char *issuer_attribute; + + /** + * The delegated attribute + */ + char *subject_attribute; +}; + +/** + * DLL for record + */ +struct DelegateRecordEntry +{ + /** + * DLL + */ + struct DelegateRecordEntry *next; + + /** + * DLL + */ + struct DelegateRecordEntry *prev; + + /** + * Number of references in delegation chains + */ + uint32_t refcount; + + /** + * Payload + */ + struct GNUNET_ABD_Delegate *delegate; +}; + +/** + * DLL used for delegations + * Used for OR delegations + */ +struct DelegationQueueEntry +{ + /** + * DLL + */ + struct DelegationQueueEntry *next; + + /** + * DLL + */ + struct DelegationQueueEntry *prev; + + /** + * 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; + + /** + * Verify handle + */ + struct VerifyRequestHandle *handle; + + /** + * Parent attribute delegation + */ + struct DelegationQueueEntry *parent; + + /** + * Issuer key + */ + 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 + */ + char *issuer_attribute; + + /** + * The current attribute to look up + */ + char *lookup_attribute; + + /** + * Trailing attribute context + */ + char *attr_trailer; + + /** + * Still to resolve delegation as string + */ + char *unresolved_attribute_delegation; + + /** + * The delegation chain entry + */ + struct DelegationChainEntry *delegation_chain_entry; + + /** + * True if added by backward resolution + */ + bool from_bw; +}; + + +/** + * Handle to a lookup operation from api + */ +struct VerifyRequestHandle +{ + /** + * True if created by a collect request. + */ + bool is_collect; + /** + * We keep these in a DLL. + */ + struct VerifyRequestHandle *next; + + /** + * We keep these in a DLL. + */ + struct VerifyRequestHandle *prev; + + /** + * Handle to the requesting client + */ + struct GNUNET_SERVICE_Client *client; + + /** + * 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; + + /** + * List for bidirectional matching + */ + struct DelegationSetQueueEntry *dsq_head; + + /** + * List for bidirectional matching + */ + struct DelegationSetQueueEntry *dsq_tail; + + /** + * Issuer public key + */ + struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key; + + /** + * Issuer attribute + */ + char *issuer_attribute; + + /** + * Subject public key + */ + struct GNUNET_CRYPTO_EcdsaPublicKey subject_key; + + /** + * Delegate DLL + */ + struct DelegateRecordEntry *del_chain_head; + + /** + * Delegate DLL + */ + struct DelegateRecordEntry *del_chain_tail; + + /** + * Delegate DLL size + */ + uint32_t del_chain_size; + + /** + * Current Delegation Pointer + */ + struct DelegationQueueEntry *current_delegation; + + /** + * request id + */ + uint32_t request_id; + + /** + * Pending lookups + */ + uint64_t pending_lookups; + + /** + * Direction of the resolution algo + */ + enum GNUNET_ABD_AlgoDirectionFlags resolution_algo; + + /** + * Delegate iterator for lookup + */ + struct GNUNET_NAMESTORE_QueueEntry *dele_qe; +}; + + +/** + * Head of the DLL. + */ +static struct VerifyRequestHandle *vrh_head = NULL; + +/** + * Tail of the DLL. + */ +static struct VerifyRequestHandle *vrh_tail = NULL; + +/** + * Handle to the statistics service + */ +static struct GNUNET_STATISTICS_Handle *statistics; + +/** + * Handle to GNS service. + */ +static struct GNUNET_GNS_Handle *gns; + +/** + * Handle to namestore service + */ +static struct GNUNET_NAMESTORE_Handle *namestore; + +static void +print_deleset (struct DelegationSetQueueEntry *dsentry, char *text) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "%s %s.%s <- %s.%s\n", + text, + GNUNET_CRYPTO_ecdsa_public_key_to_string ( + &dsentry->delegation_chain_entry->issuer_key), + dsentry->delegation_chain_entry->issuer_attribute, + GNUNET_CRYPTO_ecdsa_public_key_to_string ( + &dsentry->delegation_chain_entry->subject_key), + dsentry->delegation_chain_entry->subject_attribute); +} + +static void +cleanup_dsq_entry (struct DelegationSetQueueEntry *ds_entry) +{ + GNUNET_free_non_null (ds_entry->issuer_key); + GNUNET_free_non_null (ds_entry->issuer_attribute); + GNUNET_free_non_null (ds_entry->attr_trailer); + // those fields are only set/used in bw search + if (ds_entry->from_bw) + { + GNUNET_free_non_null (ds_entry->lookup_attribute); + GNUNET_free_non_null (ds_entry->unresolved_attribute_delegation); + } + if (NULL != ds_entry->lookup_request) + { + GNUNET_GNS_lookup_cancel (ds_entry->lookup_request); + ds_entry->lookup_request = NULL; + } + if (NULL != ds_entry->delegation_chain_entry) + { + GNUNET_free_non_null ( + ds_entry->delegation_chain_entry->subject_attribute); + GNUNET_free_non_null (ds_entry->delegation_chain_entry->issuer_attribute); + GNUNET_free (ds_entry->delegation_chain_entry); + } + // Free DQ entries + for(struct DelegationQueueEntry *dq_entry = ds_entry->queue_entries_head; + NULL != ds_entry->queue_entries_head; + dq_entry = ds_entry->queue_entries_head) + { + GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head, + ds_entry->queue_entries_tail, + dq_entry); + GNUNET_free (dq_entry); + } + GNUNET_free (ds_entry); +} + +static void +cleanup_handle (struct VerifyRequestHandle *vrh) +{ + struct DelegateRecordEntry *del_entry; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up...\n"); + + if (NULL != vrh->dsq_head) + { + for (struct DelegationSetQueueEntry *ds_entry = vrh->dsq_head; NULL != vrh->dsq_head; + ds_entry = vrh->dsq_head) + { + GNUNET_CONTAINER_DLL_remove (vrh->dsq_head, vrh->dsq_tail, ds_entry); + cleanup_dsq_entry(ds_entry); + } + } + if (NULL != vrh->del_chain_head) + { + for (del_entry = vrh->del_chain_head; NULL != vrh->del_chain_head; + del_entry = vrh->del_chain_head) + { + GNUNET_CONTAINER_DLL_remove (vrh->del_chain_head, + vrh->del_chain_tail, + del_entry); + GNUNET_free_non_null (del_entry->delegate); + GNUNET_free (del_entry); + } + } + GNUNET_free_non_null (vrh->issuer_attribute); + GNUNET_free (vrh); +} + +static void +shutdown_task (void *cls) +{ + struct VerifyRequestHandle *vrh; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down!\n"); + + while (NULL != (vrh = vrh_head)) + { + // ABD_resolver_lookup_cancel (clh->lookup); + GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh); + cleanup_handle (vrh); + } + + if (NULL != gns) + { + GNUNET_GNS_disconnect (gns); + gns = NULL; + } + if (NULL != namestore) + { + GNUNET_NAMESTORE_disconnect (namestore); + namestore = NULL; + } + if (NULL != statistics) + { + GNUNET_STATISTICS_destroy (statistics, GNUNET_NO); + statistics = NULL; + } +} + +static void +send_intermediate_response(struct VerifyRequestHandle *vrh, struct DelegationChainEntry *ch_entry, bool is_bw){ + struct DelegationChainIntermediateMessage *rmsg; + struct GNUNET_MQ_Envelope *env; + struct GNUNET_ABD_Delegation *dd; + size_t size; + + // Don't report immediate results during collect + if(vrh->is_collect) + return; + + dd = GNUNET_new (struct GNUNET_ABD_Delegation); + dd->issuer_key = ch_entry->issuer_key; + dd->subject_key = ch_entry->subject_key; + dd->issuer_attribute = ch_entry->issuer_attribute; + dd->issuer_attribute_len = strlen (ch_entry->issuer_attribute) + 1; + dd->subject_attribute_len = 0; + dd->subject_attribute = NULL; + if (NULL != ch_entry->subject_attribute) + { + dd->subject_attribute = ch_entry->subject_attribute; + dd->subject_attribute_len = strlen (ch_entry->subject_attribute) + 1; + } + + + size = GNUNET_ABD_delegation_chain_get_size (1, + dd, + 0, + NULL); + + env = GNUNET_MQ_msg_extra (rmsg, + size, + GNUNET_MESSAGE_TYPE_ABD_INTERMEDIATE_RESULT); + // Assign id so that client can find associated request + rmsg->id = vrh->request_id; + rmsg->is_bw = htons(is_bw); + rmsg->size = htonl(size); + + GNUNET_assert ( + -1 != GNUNET_ABD_delegation_chain_serialize (1, + dd, + 0, + NULL, + size, + (char *) &rmsg[1])); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (vrh->client), env); +} + +static void +send_lookup_response (struct VerifyRequestHandle *vrh) +{ + struct GNUNET_MQ_Envelope *env; + struct DelegationChainResultMessage *rmsg; + struct DelegationChainEntry *dce; + struct GNUNET_ABD_Delegation dd[vrh->delegation_chain_size]; + struct GNUNET_ABD_Delegate dele[vrh->del_chain_size]; + struct DelegateRecordEntry *del; + struct DelegateRecordEntry *tmp; + size_t size; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending response\n"); + dce = vrh->delegation_chain_head; + for (uint32_t i = 0; i < vrh->delegation_chain_size; i++) + { + 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; + dd[i].subject_attribute = NULL; + if (NULL != dce->subject_attribute) + { + dd[i].subject_attribute = dce->subject_attribute; + dd[i].subject_attribute_len = strlen (dce->subject_attribute) + 1; + } + dce = dce->next; + } + + // Remove all not needed credentials + for (del = vrh->del_chain_head; NULL != del;) + { + if (del->refcount > 0) + { + del = del->next; + continue; + } + tmp = del; + del = del->next; + GNUNET_CONTAINER_DLL_remove (vrh->del_chain_head, vrh->del_chain_tail, tmp); + GNUNET_free (tmp->delegate); + GNUNET_free (tmp); + vrh->del_chain_size--; + } + + // Get serialized record data + // Append at the end of rmsg + del = vrh->del_chain_head; + for (uint32_t i = 0; i < vrh->del_chain_size; i++) + { + dele[i].issuer_key = del->delegate->issuer_key; + dele[i].subject_key = del->delegate->subject_key; + dele[i].issuer_attribute_len = strlen (del->delegate->issuer_attribute) + 1; + dele[i].issuer_attribute = del->delegate->issuer_attribute; + dele[i].subject_attribute_len = del->delegate->subject_attribute_len; + dele[i].subject_attribute = del->delegate->subject_attribute; + dele[i].expiration = del->delegate->expiration; + dele[i].signature = del->delegate->signature; + del = del->next; + } + size = + GNUNET_ABD_delegation_chain_get_size (vrh->delegation_chain_size, + dd, + vrh->del_chain_size, + dele); + env = GNUNET_MQ_msg_extra (rmsg, + size, + GNUNET_MESSAGE_TYPE_ABD_VERIFY_RESULT); + // Assign id so that client can find associated request + rmsg->id = vrh->request_id; + rmsg->d_count = htonl (vrh->delegation_chain_size); + rmsg->c_count = htonl (vrh->del_chain_size); + + if (0 < vrh->del_chain_size) + rmsg->del_found = htonl (GNUNET_YES); + else + rmsg->del_found = htonl (GNUNET_NO); + + GNUNET_assert ( + -1 != + GNUNET_ABD_delegation_chain_serialize (vrh->delegation_chain_size, + dd, + vrh->del_chain_size, + dele, + size, + (char *) &rmsg[1])); + + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (vrh->client), env); + GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh); + cleanup_handle (vrh); + GNUNET_STATISTICS_update (statistics, + "Completed verifications", + 1, + GNUNET_NO); +} + +static char * +partial_match (char *tmp_trail, + char *tmp_subattr, + char *parent_trail, + char *issuer_attribute) +{ + char *saveptr1, *saveptr2; + char *trail_token; + char *sub_token; + char *attr_trailer; + + // tok both, parent->attr_trailer and del->sub_attr to see how far they match, + // take rest of parent trailer (only when del->sub_attr token is null), and + // create new/actual trailer with del->iss_attr + trail_token = strtok_r (tmp_trail, ".", &saveptr1); + sub_token = strtok_r (tmp_subattr, ".", &saveptr2); + while (NULL != trail_token && NULL != sub_token) + { + if (0 == strcmp (trail_token, sub_token)) + { + // good, matches, remove + } + else + { + // not relevant for solving the chain, end for iteration here + return NULL; + } + + trail_token = strtok_r (NULL, ".", &saveptr1); + sub_token = strtok_r (NULL, ".", &saveptr2); + } + // skip this entry and go to next for if: + // 1. at some point the attr of the trailer and the subject dont match + // 2. the trailer is NULL, but the subject has more attributes + // Reason: This will lead to "startzone.attribute" but we're looking for a solution + // for "<- startzone" + if (NULL == trail_token) + { + return NULL; + } + + // do not have to check sub_token == NULL, if both would be NULL + // at the same time, the complete match part above should have triggered already + + // otherwise, above while only ends when sub_token == NULL + GNUNET_asprintf (&attr_trailer, "%s", trail_token); + trail_token = strtok_r (NULL, ".", &saveptr1); + while (NULL != trail_token) + { + GNUNET_asprintf (&attr_trailer, "%s.%s", parent_trail, trail_token); + trail_token = strtok_r (NULL, ".", &saveptr1); + } + GNUNET_asprintf (&attr_trailer, "%s.%s", issuer_attribute, attr_trailer); + return attr_trailer; +} + +static int +handle_bidirectional_match (struct DelegationSetQueueEntry *actual_entry, + struct DelegationSetQueueEntry *match_entry, + struct VerifyRequestHandle *vrh) +{ + struct DelegationSetQueueEntry *old_fw_parent; + struct DelegationSetQueueEntry *fw_entry = actual_entry; + struct DelegationSetQueueEntry *last_entry = match_entry; + // parent fixing, combine backward and forward chain parts + while (NULL != fw_entry->parent_queue_entry) + { + old_fw_parent = fw_entry->parent_queue_entry->parent_set; + // set parent + fw_entry->parent_queue_entry->parent_set = last_entry; + + last_entry = fw_entry; + fw_entry = old_fw_parent; + } + // set last entry of chain as actual_entry + //actual_entry = last_entry; + // set refcount, loop all delegations + for (struct DelegateRecordEntry *del_entry = vrh->del_chain_head; + del_entry != NULL; + del_entry = del_entry->next) + { + if (0 != memcmp (&last_entry->delegation_chain_entry->subject_key, + &del_entry->delegate->issuer_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) + continue; + if (0 != strcmp (last_entry->delegation_chain_entry->subject_attribute, + del_entry->delegate->issuer_attribute)) + continue; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found delegate.\n"); + // increase refcount of the start delegation + del_entry->refcount++; + } + // backtrack + for (struct DelegationSetQueueEntry *tmp_set = last_entry; + NULL != tmp_set->parent_queue_entry; + tmp_set = tmp_set->parent_queue_entry->parent_set) + { + tmp_set->parent_queue_entry->required_solutions--; + + // add new found entry to vrh + vrh->delegation_chain_size++; + GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head, + vrh->delegation_chain_tail, + tmp_set->delegation_chain_entry); + + // if one node on the path still needs solutions, this current + // patch cannot fullfil the conditions and therefore stops here + // however, it is in the vrh and can be used by the other paths + // related to this path/collection/verification + if (0 < tmp_set->parent_queue_entry->required_solutions) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Chain requires more solutions, waiting...\n"); + return GNUNET_NO; + } + } + return GNUNET_YES; +} + +static void +forward_resolution (void *cls, + uint32_t rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d entries.\n", rd_count); + + struct VerifyRequestHandle *vrh; + struct DelegationSetQueueEntry *current_set; + struct DelegationSetQueueEntry *ds_entry; + struct DelegationQueueEntry *dq_entry; + + current_set = cls; + // set handle to NULL (as el = NULL) + current_set->lookup_request = NULL; + vrh = current_set->handle; + vrh->pending_lookups--; + + // Loop record entries + for (uint32_t i = 0; i < rd_count; i++) + { + if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type) + continue; + + // Start deserialize into Delegate + struct GNUNET_ABD_Delegate *del; + del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size); + + // Start: Create DQ Entry + dq_entry = GNUNET_new (struct DelegationQueueEntry); + // AND delegations are not possible, only 1 solution + dq_entry->required_solutions = 1; + dq_entry->parent_set = current_set; + + // Insert it into the current set + GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head, + current_set->queue_entries_tail, + dq_entry); + + // Start: Create DS Entry + ds_entry = GNUNET_new (struct DelegationSetQueueEntry); + GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry); + ds_entry->from_bw = false; + + // (1) A.a <- A.b.c + // (2) A.b <- D.d + // (3) D.d <- E + // (4) E.c <- F.c + // (5) F.c <- G + // Possibilities: + // 1. complete match: trailer = 0, validate + // 2. partial match: replace + // 3. new solution: replace, add trailer + + // At resolution chain start trailer of parent is NULL + if (NULL == current_set->attr_trailer) + { + // for (5) F.c <- G, remember .c when going upwards + ds_entry->attr_trailer = GNUNET_strdup (del->issuer_attribute); + } + else + { + if (0 == del->subject_attribute_len) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: New solution\n"); + // new solution + // create new trailer del->issuer_attribute, ds_entry->attr_trailer + GNUNET_asprintf (&ds_entry->attr_trailer, + "%s.%s", + del->issuer_attribute, + current_set->attr_trailer); + } + else if (0 == strcmp (del->subject_attribute, current_set->attr_trailer)) + { + // complete match + // new trailer == issuer attribute (e.g. (5) to (4)) + ds_entry->attr_trailer = GNUNET_strdup (del->issuer_attribute); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: Partial match\n"); + // partial match + + char *trail = partial_match (GNUNET_strdup (current_set->attr_trailer), + GNUNET_strdup (del->subject_attribute), + current_set->attr_trailer, + GNUNET_strdup (del->issuer_attribute)); + + // if null: skip this record entry (reasons: mismatch or overmatch, both not relevant) + if (NULL == trail) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Entry not relevant, discarding: %s.%s <- %s.%s\n", + GNUNET_CRYPTO_ecdsa_public_key_to_string ( + &del->issuer_key), + del->issuer_attribute, + GNUNET_CRYPTO_ecdsa_public_key_to_string ( + &del->subject_key), + del->subject_attribute); + continue; + } + else + ds_entry->attr_trailer = trail; + } + } + + + // Start: Credential Chain Entry + // issuer key is subject key, who needs to be contacted to resolve this (forward, therefore subject) + ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); + GNUNET_memcpy (ds_entry->issuer_key, + &del->subject_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + + ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry); + ds_entry->delegation_chain_entry->subject_key = del->subject_key; + if (0 < del->subject_attribute_len) + ds_entry->delegation_chain_entry->subject_attribute = + GNUNET_strdup (del->subject_attribute); + ds_entry->delegation_chain_entry->issuer_key = del->issuer_key; + ds_entry->delegation_chain_entry->issuer_attribute = + GNUNET_strdup (del->issuer_attribute); + + // Found new entry, repoting intermediate result + send_intermediate_response(vrh, ds_entry->delegation_chain_entry, false); + + // current delegation as parent + ds_entry->parent_queue_entry = dq_entry; + + // Check for solution + // if: issuer key we looking for + if (0 == memcmp (&del->issuer_key, + &vrh->issuer_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) + { + // if: issuer attr we looking for + if (0 == strcmp (del->issuer_attribute, vrh->issuer_attribute)) + { + // if: complete match, meaning new trailer == issuer attr + if (0 == strcmp (vrh->issuer_attribute, ds_entry->attr_trailer)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: Solution\n"); + + // Add found solution into delegation_chain + struct DelegationSetQueueEntry *tmp_set; + for (tmp_set = ds_entry; NULL != tmp_set->parent_queue_entry; + tmp_set = tmp_set->parent_queue_entry->parent_set) + { + 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); + } + } + + // Increase refcount for this delegate + for (struct DelegateRecordEntry *del_entry = vrh->del_chain_head; + del_entry != NULL; + del_entry = del_entry->next) + { + if (0 == memcmp (&del_entry->delegate->issuer_key, + &vrh->delegation_chain_head->subject_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) + { + if (0 == strcmp (del_entry->delegate->issuer_attribute, + vrh->delegation_chain_head->subject_attribute)) + { + del_entry->refcount++; + } + } + } + + send_lookup_response (vrh); + return; + } + } + } + + // Check for bidirectional crossmatch + for (struct DelegationSetQueueEntry *del_entry = vrh->dsq_head; + del_entry != NULL; + del_entry = del_entry->next) + { + // only check entries not by backward algorithm + if (del_entry->from_bw) + { + // key of list entry matches actual key + if (0 == memcmp (&del_entry->delegation_chain_entry->subject_key, + &ds_entry->delegation_chain_entry->issuer_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) + { + // compare entry subject attributes to this trailer (iss attr + old trailer) + if (0 == strcmp (del_entry->unresolved_attribute_delegation, + ds_entry->attr_trailer)) + { + print_deleset (del_entry, "Forward:"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Forward: Found match with above!\n"); + + // one node on the path still needs solutions: return + if (GNUNET_NO == + handle_bidirectional_match (ds_entry, del_entry, vrh)) + return; + + send_lookup_response (vrh); + return; + } + } + } + } + + // Starting a new GNS lookup + vrh->pending_lookups++; + ds_entry->handle = vrh; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting to look up trailer %s in zone %s\n", + ds_entry->attr_trailer, + GNUNET_CRYPTO_ecdsa_public_key_to_string (&del->issuer_key)); + + ds_entry->lookup_request = + GNUNET_GNS_lookup (gns, + GNUNET_GNS_EMPTY_LABEL_AT, + &del->issuer_key, + GNUNET_GNSRECORD_TYPE_DELEGATE, + GNUNET_GNS_LO_DEFAULT, + &forward_resolution, + ds_entry); + } + + if (0 == vrh->pending_lookups) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We are all out of attributes...\n"); + send_lookup_response (vrh); + return; + } +} + +static void +backward_resolution (void *cls, + uint32_t rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct VerifyRequestHandle *vrh; + const struct GNUNET_ABD_DelegationRecord *sets; + struct DelegateRecordEntry *del_pointer; + struct DelegationSetQueueEntry *current_set; + struct DelegationSetQueueEntry *ds_entry; + struct DelegationSetQueueEntry *tmp_set; + struct DelegationQueueEntry *dq_entry; + char *expanded_attr; + char *lookup_attribute; + + current_set = cls; + current_set->lookup_request = NULL; + vrh = current_set->handle; + vrh->pending_lookups--; + + // Each OR + for (uint32_t i = 0; i < rd_count; i++) + { + if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type) + continue; + + sets = rd[i].data; + struct GNUNET_ABD_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)); + + if (GNUNET_OK != + GNUNET_ABD_delegation_set_deserialize (GNUNET_ntohll ( + sets->data_size), + (const char *) &sets[1], + ntohl (sets->set_count), + set)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to deserialize!\n"); + continue; + } + 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); + // Each AND + for (uint32_t j = 0; j < ntohl (sets->set_count); j++) + { + ds_entry = GNUNET_new (struct DelegationSetQueueEntry); + GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry); + ds_entry->from_bw = true; + + 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); + } + } + + // 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); + + // Found new entry, repoting intermediate result + send_intermediate_response(vrh, ds_entry->delegation_chain_entry, true); + + ds_entry->parent_queue_entry = dq_entry; // current_delegation; + + /** + * Check if this delegation already matches one of our credentials + */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking for cred match\n"); + + for (del_pointer = vrh->del_chain_head; del_pointer != NULL; + del_pointer = del_pointer->next) + { + // If key and attribute match credential: continue and backtrack + if (0 != memcmp (&set[j].subject_key, + &del_pointer->delegate->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, + del_pointer->delegate->issuer_attribute); + + if (0 != strcmp (ds_entry->unresolved_attribute_delegation, + del_pointer->delegate->issuer_attribute)) + continue; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found issuer\n"); + // increase refcount of the start delegation + del_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 the break above is not called the condition of the for is met + 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_DEBUG, + "Building new lookup request from %s\n", + ds_entry->unresolved_attribute_delegation); + // Continue with next/new 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, "."); + if (NULL == next_attr) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to parse next attribute\n"); + continue; + } + GNUNET_asprintf (&lookup_attribute, "%s", 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); + } + + // Check for bidirectional crossmatch + for (struct DelegationSetQueueEntry *del_entry = vrh->dsq_head; + del_entry != NULL; + del_entry = del_entry->next) + { + // only check entries added by forward algorithm + if (!del_entry->from_bw) + { + // key of list entry matches actual key + if (0 == memcmp (&del_entry->delegation_chain_entry->issuer_key, + &ds_entry->delegation_chain_entry->subject_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) + { + // compare entry subject attributes to this trailer (iss attr + old trailer) + if (0 == strcmp (del_entry->attr_trailer, + ds_entry->unresolved_attribute_delegation)) + { + print_deleset (del_entry, "Backward:"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Backward: Found match with above!\n"); + + // if one node on the path still needs solutions: return + if (GNUNET_NO == + handle_bidirectional_match (del_entry, ds_entry, vrh)) + break; + + // Send lookup response + send_lookup_response (vrh); + return; + } + } + } + } + + // Starting a new GNS lookup + 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); + } + } + + if (0 == vrh->pending_lookups) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We are all out of attributes...\n"); + send_lookup_response (vrh); + return; + } +} + + +/** + * Result from GNS lookup. + * + * @param cls the closure (our client lookup handle) + */ +static int +delegation_chain_bw_resolution_start (void *cls) +{ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Start Backward Resolution...\n"); + + struct VerifyRequestHandle *vrh = cls; + struct DelegationSetQueueEntry *ds_entry; + struct DelegateRecordEntry *del_entry; + + if (0 == vrh->del_chain_size) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No delegates found\n"); + send_lookup_response (vrh); + return 1; + } + + // Pre-check with vrh->dele_chain_.. if match issuer_key + // Backward: check every cred entry if match issuer key + // otherwise: start at issuer and go down till match + // A.a <- ... + // X.x <- C + // Y.y <- C + // if not X.x or Y.y == A.a start at A + for (del_entry = vrh->del_chain_head; del_entry != NULL; + del_entry = del_entry->next) + { + if (0 != memcmp (&del_entry->delegate->issuer_key, + &vrh->issuer_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) + continue; + if (0 != + strcmp (del_entry->delegate->issuer_attribute, vrh->issuer_attribute)) + continue; + del_entry->refcount++; + // Found match prematurely + send_lookup_response (vrh); + return 1; + } + + + //Check for attributes from the issuer and follow the chain + //till you get the required subject's attributes + char issuer_attribute_name[strlen (vrh->issuer_attribute) + 1]; + strcpy (issuer_attribute_name, vrh->issuer_attribute); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Looking up %s\n", + issuer_attribute_name); + ds_entry = GNUNET_new (struct DelegationSetQueueEntry); + GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry); + ds_entry->from_bw = true; + ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); + GNUNET_memcpy (ds_entry->issuer_key, + &vrh->issuer_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute); + + ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry); + ds_entry->delegation_chain_entry->issuer_key = vrh->issuer_key; + ds_entry->delegation_chain_entry->issuer_attribute = + GNUNET_strdup (vrh->issuer_attribute); + + ds_entry->handle = vrh; + ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute); + ds_entry->unresolved_attribute_delegation = NULL; + vrh->pending_lookups = 1; + + // Start with backward resolution + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start Backward Resolution\n"); + + ds_entry->lookup_request = GNUNET_GNS_lookup (gns, + issuer_attribute_name, + &vrh->issuer_key, // issuer_key, + GNUNET_GNSRECORD_TYPE_ATTRIBUTE, + GNUNET_GNS_LO_DEFAULT, + &backward_resolution, + ds_entry); + return 0; +} + +static int +delegation_chain_fw_resolution_start (void *cls) +{ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Start Forward Resolution...\n"); + + struct VerifyRequestHandle *vrh = cls; + struct DelegationSetQueueEntry *ds_entry; + struct DelegateRecordEntry *del_entry; + + // set to 0 and increase on each lookup: for fw multiple lookups (may be) started + vrh->pending_lookups = 0; + + if (0 == vrh->del_chain_size) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No delegations found\n"); + send_lookup_response (vrh); + return 1; + } + + // Pre-check with vrh->dele_chain_.. if match issuer_key + // otherwise FW: start mutliple lookups for each vrh->dele_chain + // A.a <- ... + // X.x <- C + // Y.y <- C + // if not X.x or Y.y == A.a start at X and at Y + for (del_entry = vrh->del_chain_head; del_entry != NULL; + del_entry = del_entry->next) + { + if (0 != memcmp (&del_entry->delegate->issuer_key, + &vrh->issuer_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) + continue; + if (0 != + strcmp (del_entry->delegate->issuer_attribute, vrh->issuer_attribute)) + continue; + del_entry->refcount++; + // Found match prematurely + send_lookup_response (vrh); + return 1; + } + + // None match, therefore start for every delegation found a lookup chain + // Return and end collect process on first chain iss <-> sub found + + // ds_entry created belongs to the first lookup, vrh still has the + // issuer+attr we look for + for (del_entry = vrh->del_chain_head; del_entry != NULL; + del_entry = del_entry->next) + { + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Looking for %s.%s\n", + GNUNET_CRYPTO_ecdsa_public_key_to_string ( + &del_entry->delegate->issuer_key), + del_entry->delegate->issuer_attribute); + + ds_entry = GNUNET_new (struct DelegationSetQueueEntry); + GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry); + ds_entry->from_bw = false; + ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); + GNUNET_memcpy (ds_entry->issuer_key, + &del_entry->delegate->subject_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + + ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry); + ds_entry->delegation_chain_entry->subject_key = del_entry->delegate->subject_key; + ds_entry->delegation_chain_entry->subject_attribute = NULL; + ds_entry->delegation_chain_entry->issuer_key = del_entry->delegate->issuer_key; + ds_entry->delegation_chain_entry->issuer_attribute = + GNUNET_strdup (del_entry->delegate->issuer_attribute); + + ds_entry->attr_trailer = + GNUNET_strdup (del_entry->delegate->issuer_attribute); + ds_entry->handle = vrh; + + vrh->pending_lookups++; + // Start with forward resolution + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start Forward Resolution\n"); + + ds_entry->lookup_request = + GNUNET_GNS_lookup (gns, + GNUNET_GNS_EMPTY_LABEL_AT, + &del_entry->delegate->issuer_key, // issuer_key, + GNUNET_GNSRECORD_TYPE_DELEGATE, + GNUNET_GNS_LO_DEFAULT, + &forward_resolution, + ds_entry); + } + return 0; +} + +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_ABD_MAX_LENGTH) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + attr = (const char *) &v_msg[1]; + + if (strlen (attr) > GNUNET_ABD_MAX_LENGTH) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + +static void +handle_verify (void *cls, const struct VerifyMessage *v_msg) +{ + struct VerifyRequestHandle *vrh; + struct GNUNET_SERVICE_Client *client = cls; + struct DelegateRecordEntry *del_entry; + uint32_t delegate_count; + uint32_t delegate_data_size; + char attr[GNUNET_ABD_MAX_LENGTH + 1]; + char issuer_attribute[GNUNET_ABD_MAX_LENGTH + 1]; + char *attrptr = attr; + char *delegate_data; + const char *utf_in; + + 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, attr, ntohs (v_msg->issuer_attribute_len)); + issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0'; + vrh = GNUNET_new (struct VerifyRequestHandle); + vrh->is_collect = false; + GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh); + vrh->client = client; + vrh->request_id = v_msg->id; + vrh->issuer_key = v_msg->issuer_key; + vrh->subject_key = v_msg->subject_key; + vrh->issuer_attribute = GNUNET_strdup (issuer_attribute); + vrh->resolution_algo = ntohs (v_msg->resolution_algo); + + vrh->del_chain_head = NULL; + vrh->del_chain_tail = NULL; + vrh->dsq_head = NULL; + vrh->dsq_tail = NULL; + vrh->del_chain_head = NULL; + vrh->del_chain_tail = NULL; + + GNUNET_SERVICE_client_continue (vrh->client); + if (0 == strlen (issuer_attribute)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer attribute provided!\n"); + send_lookup_response (vrh); + return; + } + + // Parse delegates from verifaction message + delegate_count = ntohl (v_msg->d_count); + delegate_data_size = ntohs (v_msg->header.size) - + sizeof (struct VerifyMessage) - + ntohs (v_msg->issuer_attribute_len) - 1; + struct GNUNET_ABD_Delegate delegates[delegate_count]; + memset (delegates, + 0, + sizeof (struct GNUNET_ABD_Delegate) * delegate_count); + delegate_data = (char *) &v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1; + if (GNUNET_OK != GNUNET_ABD_delegates_deserialize (delegate_data_size, + delegate_data, + delegate_count, + delegates)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot deserialize delegates!\n"); + send_lookup_response (vrh); + return; + } + + // Prepare vrh delegation chain for later validation + for (uint32_t i = 0; i < delegate_count; i++) + { + del_entry = GNUNET_new (struct DelegateRecordEntry); + del_entry->delegate = + GNUNET_malloc (sizeof (struct GNUNET_ABD_Delegate) + + delegates[i].issuer_attribute_len + 1); + GNUNET_memcpy (del_entry->delegate, + &delegates[i], + sizeof (struct GNUNET_ABD_Delegate)); + GNUNET_memcpy (&del_entry->delegate[1], + delegates[i].issuer_attribute, + delegates[i].issuer_attribute_len); + del_entry->delegate->issuer_attribute_len = + delegates[i].issuer_attribute_len; + del_entry->delegate->issuer_attribute = (char *) &del_entry->delegate[1]; + GNUNET_CONTAINER_DLL_insert_tail (vrh->del_chain_head, + vrh->del_chain_tail, + del_entry); + vrh->del_chain_size++; + } + + // Switch resolution algo + if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo && + GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo) + { + if(1 == delegation_chain_fw_resolution_start (vrh)) + return; + delegation_chain_bw_resolution_start (vrh); + } + else if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo) + { + delegation_chain_bw_resolution_start (vrh); + } + else if (GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo) + { + delegation_chain_fw_resolution_start (vrh); + } +} + +static void +handle_delegate_collection_error_cb (void *cls) +{ + struct VerifyRequestHandle *vrh = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got disconnected from namestore database.\n"); + vrh->dele_qe = NULL; + send_lookup_response (vrh); +} + +static void +delegate_collection_finished (void *cls) +{ + struct VerifyRequestHandle *vrh = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done collecting delegates.\n"); + + // if both are set: bidirectional search, meaning start both chain resolutions + if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo && + GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo) + { + // if premature match found don't start bw resultion + if(1 == delegation_chain_fw_resolution_start (vrh)) + return; + delegation_chain_bw_resolution_start (vrh); + } + else if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo) + { + delegation_chain_bw_resolution_start (vrh); + } + else if (GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo) + { + delegation_chain_fw_resolution_start (vrh); + } +} + +static void +handle_delegate_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_ABD_Delegate *del; + struct DelegateRecordEntry *del_entry; + int cred_record_count; + cred_record_count = 0; + vrh->dele_qe = NULL; + + for (uint32_t i = 0; i < rd_count; i++) + { + if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type) + continue; + cred_record_count++; + del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size); + if (NULL == del) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid delegate found\n"); + continue; + } + // only add the entries that are explicity marked as private + // and therefor symbolize the end of a chain + if (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE) + { + del_entry = GNUNET_new (struct DelegateRecordEntry); + del_entry->delegate = del; + GNUNET_CONTAINER_DLL_insert_tail (vrh->del_chain_head, + vrh->del_chain_tail, + del_entry); + vrh->del_chain_size++; + } + } + + delegate_collection_finished (vrh); +} + +static void +handle_collect (void *cls, const struct CollectMessage *c_msg) +{ + char attr[GNUNET_ABD_MAX_LENGTH + 1]; + char issuer_attribute[GNUNET_ABD_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); + vrh->is_collect = true; + 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); + vrh->resolution_algo = ntohs (c_msg->resolution_algo); + + vrh->del_chain_head = NULL; + vrh->del_chain_tail = NULL; + vrh->dsq_head = NULL; + vrh->dsq_tail = NULL; + vrh->del_chain_head = NULL; + vrh->del_chain_tail = NULL; + + if (0 == strlen (issuer_attribute)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer attribute provided!\n"); + send_lookup_response (vrh); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting delegates for subject\n"); + + // Get all delegates from subject + vrh->dele_qe = + GNUNET_NAMESTORE_records_lookup (namestore, + &c_msg->subject_key, + GNUNET_GNS_EMPTY_LABEL_AT, + &handle_delegate_collection_error_cb, + vrh, + &handle_delegate_collection_cb, + vrh); + GNUNET_SERVICE_client_continue (vrh->client); +} + + +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_ABD_MAX_LENGTH) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + attr = (const char *) &c_msg[1]; + + if (('\0' != attr[msg_size - sizeof (struct CollectMessage) - 1]) || + (strlen (attr) > GNUNET_ABD_MAX_LENGTH)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + +static void +client_disconnect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + void *app_ctx) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); +} + +static void * +client_connect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + struct GNUNET_MQ_Handle *mq) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client); + return client; +} + +/** + * Process Credential requests. + * + * @param cls closure + * @param c configuration to use + * @param handle service handle + */ +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *c, + struct GNUNET_SERVICE_Handle *handle) +{ + + gns = GNUNET_GNS_connect (c); + if (NULL == gns) + { + 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 ("abd", c); + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); +} + + +/** + * Define "main" method using service macro + */ +GNUNET_SERVICE_MAIN ( + "abd", + GNUNET_SERVICE_OPTION_NONE, + &run, + &client_connect_cb, + &client_disconnect_cb, + NULL, + GNUNET_MQ_hd_var_size (verify, + GNUNET_MESSAGE_TYPE_ABD_VERIFY, + struct VerifyMessage, + NULL), + GNUNET_MQ_hd_var_size (collect, + GNUNET_MESSAGE_TYPE_ABD_COLLECT, + struct CollectMessage, + NULL), + GNUNET_MQ_handler_end ()); + +/* end of gnunet-service-abd.c */ diff --git a/src/abd/plugin_gnsrecord_abd.c b/src/abd/plugin_gnsrecord_abd.c new file mode 100644 index 000000000..811878627 --- /dev/null +++ b/src/abd/plugin_gnsrecord_abd.c @@ -0,0 +1,349 @@ +/* + 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 . + + SPDX-License-Identifier: AGPL3.0-or-later +*/ + +/** + * @file abd/plugin_gnsrecord_abd.c + * @brief gnsrecord plugin to provide the API for ABD records + * @author Martin Schanzenbach + */ +#include "platform.h" + +#include "gnunet_util_lib.h" + +#include "delegate_misc.h" +#include "abd_serialization.h" +#include "gnunet_abd_service.h" +#include "gnunet_gnsrecord_lib.h" +#include "gnunet_gnsrecord_plugin.h" +#include "gnunet_signatures.h" +/** + * Convert the 'value' of a record to a string. + * + * @param cls closure, unused + * @param type type of the record + * @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 * +abd_value_to_string (void *cls, + uint32_t type, + const void *data, + size_t data_size) +{ + const char *cdata; + + switch (type) + { + case GNUNET_GNSRECORD_TYPE_ATTRIBUTE: + { + struct GNUNET_ABD_DelegationRecord sets; + char *attr_str; + char *subject_pkey; + char *tmp_str; + int i; + if (data_size < sizeof (struct GNUNET_ABD_DelegationRecord)) + return NULL; /* malformed */ + + GNUNET_memcpy (&sets, data, sizeof (sets)); + cdata = data; + + struct GNUNET_ABD_DelegationSet set[ntohl (sets.set_count)]; + if (GNUNET_OK != + GNUNET_ABD_delegation_set_deserialize (GNUNET_ntohll ( + sets.data_size), + &cdata[sizeof (sets)], + ntohl (sets.set_count), + set)) + return NULL; + + for (i = 0; i < ntohl (sets.set_count); i++) + { + subject_pkey = + GNUNET_CRYPTO_ecdsa_public_key_to_string (&set[i].subject_key); + + if (0 == set[i].subject_attribute_len) + { + if (0 == i) + { + GNUNET_asprintf (&attr_str, "%s", subject_pkey); + } + else + { + GNUNET_asprintf (&tmp_str, "%s,%s", attr_str, subject_pkey); + GNUNET_free (attr_str); + attr_str = tmp_str; + } + } + else + { + if (0 == i) + { + GNUNET_asprintf (&attr_str, + "%s %s", + subject_pkey, + set[i].subject_attribute); + } + else + { + GNUNET_asprintf (&tmp_str, + "%s,%s %s", + attr_str, + subject_pkey, + set[i].subject_attribute); + GNUNET_free (attr_str); + attr_str = tmp_str; + } + } + GNUNET_free (subject_pkey); + } + return attr_str; + } + case GNUNET_GNSRECORD_TYPE_DELEGATE: + { + struct GNUNET_ABD_Delegate *cred; + char *cred_str; + + cred = GNUNET_ABD_delegate_deserialize (data, data_size); + cred_str = GNUNET_ABD_delegate_to_string (cred); + GNUNET_free (cred); + return cred_str; + } + default: + return NULL; + } +} + + +/** + * Convert human-readable version of a 'value' of a record to the binary + * representation. + * + * @param cls closure, unused + * @param type type of the record + * @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 +abd_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_GNSRECORD_TYPE_ATTRIBUTE: + { + struct GNUNET_ABD_DelegationRecord *sets; + char attr_str[253 + 1]; + char subject_pkey[52 + 1]; + char *token; + char *tmp_str; + int matches = 0; + int entries; + size_t tmp_data_size; + int i; + + tmp_str = GNUNET_strdup (s); + token = strtok (tmp_str, ","); + entries = 0; + tmp_data_size = 0; + *data_size = sizeof (struct GNUNET_ABD_DelegationRecord); + while (NULL != token) + { + // also fills the variables subject_pley and attr_str if "regex"-like match + matches = SSCANF (token, "%s %s", subject_pkey, attr_str); + + if (0 == matches) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _ ("Unable to parse ATTR record string `%s'\n"), + s); + GNUNET_free (tmp_str); + return GNUNET_SYSERR; + } + + entries++; + token = strtok (NULL, ","); + } + GNUNET_free (tmp_str); + + tmp_str = GNUNET_strdup (s); + token = strtok (tmp_str, ","); + if (NULL == token) + { + GNUNET_free (tmp_str); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed string %s\n", s); + return GNUNET_SYSERR; + } + + struct GNUNET_ABD_DelegationSet set[entries]; + // sets memory to be 0, starting at *set for the size of struct * entries + memset (set, 0, sizeof (struct GNUNET_ABD_DelegationSet) * entries); + for (i = 0; i < entries; i++) + { + matches = SSCANF (token, "%s %s", subject_pkey, attr_str); + + // sets the public key for the set entry + GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey, + strlen (subject_pkey), + &set[i].subject_key); + + // If not just key, also set subject attribute (Not A.a <- B but A.a <- B.b) + if (2 == matches) + { + set[i].subject_attribute_len = strlen (attr_str) + 1; + set[i].subject_attribute = GNUNET_strdup (attr_str); + } + // If more entries, then token string can take the next entry (separated by ',') by calling strtok again + token = strtok (NULL, ","); + } + tmp_data_size = GNUNET_ABD_delegation_set_get_size (entries, set); + + if (-1 == tmp_data_size) + { + GNUNET_free (tmp_str); + return GNUNET_SYSERR; + } + *data_size += tmp_data_size; + *data = sets = GNUNET_malloc (*data_size); + GNUNET_ABD_delegation_set_serialize (entries, + set, + tmp_data_size, + (char *) &sets[1]); + for (i = 0; i < entries; i++) + { + if (0 != set[i].subject_attribute_len) + GNUNET_free ((char *) set[i].subject_attribute); + } + sets->set_count = htonl (entries); + sets->data_size = GNUNET_htonll (tmp_data_size); + + GNUNET_free (tmp_str); + return GNUNET_OK; + } + case GNUNET_GNSRECORD_TYPE_DELEGATE: + { + struct GNUNET_ABD_Delegate *cred; + cred = GNUNET_ABD_delegate_from_string (s); + + *data_size = GNUNET_ABD_delegate_serialize (cred, (char **) data); + + return GNUNET_OK; + } + default: + return GNUNET_SYSERR; + } +} + + +/** + * Mapping of record type numbers to human-readable + * record type names. + */ +static struct +{ + const char *name; + uint32_t number; +} name_map[] = {{"ATTR", GNUNET_GNSRECORD_TYPE_ATTRIBUTE}, + {"DEL", GNUNET_GNSRECORD_TYPE_DELEGATE}, + {NULL, UINT32_MAX}}; + + +/** + * Convert a type name (i.e. "AAAA") to the corresponding number. + * + * @param cls closure, unused + * @param gns_typename name to convert + * @return corresponding number, UINT32_MAX on error + */ +static uint32_t +abd_typename_to_number (void *cls, const char *gns_typename) +{ + unsigned int i; + + i = 0; + while ((name_map[i].name != NULL) && + (0 != strcasecmp (gns_typename, name_map[i].name))) + i++; + return name_map[i].number; +} + + +/** + * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A") + * + * @param cls closure, unused + * @param type number of a type to convert + * @return corresponding typestring, NULL on error + */ +static const char * +abd_number_to_typename (void *cls, uint32_t type) +{ + unsigned int i; + + i = 0; + while ((name_map[i].name != NULL) && (type != name_map[i].number)) + i++; + return name_map[i].name; +} + + +/** + * Entry point for the plugin. + * + * @param cls NULL + * @return the exported block API + */ +void * +libgnunet_plugin_gnsrecord_abd_init (void *cls) +{ + struct GNUNET_GNSRECORD_PluginFunctions *api; + + api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions); + api->value_to_string = &abd_value_to_string; + api->string_to_value = &abd_string_to_value; + api->typename_to_number = &abd_typename_to_number; + api->number_to_typename = &abd_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_gnsrecord_abd_done (void *cls) +{ + struct GNUNET_GNSRECORD_PluginFunctions *api = cls; + + GNUNET_free (api); + return NULL; +} + +/* end of plugin_gnsrecord_abd.c */ diff --git a/src/abd/plugin_rest_credential.c b/src/abd/plugin_rest_credential.c new file mode 100644 index 000000000..513ddfff9 --- /dev/null +++ b/src/abd/plugin_rest_credential.c @@ -0,0 +1,1174 @@ +/* + This file is part of GNUnet. + Copyright (C) 2012-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 . + + SPDX-License-Identifier: AGPL3.0-or-later + */ +/** + * @author Martin Schanzenbach + * @file credential/plugin_rest_credential.c + * @brief GNUnet CREDENTIAL REST plugin + * + */ + +#include "platform.h" +#include "gnunet_rest_plugin.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define GNUNET_REST_API_NS_CREDENTIAL "/credential" + +#define GNUNET_REST_API_NS_CREDENTIAL_ISSUE "/credential/issue" + +#define GNUNET_REST_API_NS_CREDENTIAL_VERIFY "/credential/verify" + +#define GNUNET_REST_API_NS_CREDENTIAL_COLLECT "/credential/collect" + +#define GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION "expiration" + +#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY "subject_key" + +#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO "subject" + +#define GNUNET_REST_JSONAPI_CREDENTIAL "credential" + +#define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential" + +#define GNUNET_REST_JSONAPI_DELEGATIONS "delegations" + +#define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute" + +#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential" + +/** + * @brief struct returned by the initialization function of the plugin + */ +struct Plugin +{ + const struct GNUNET_CONFIGURATION_Handle *cfg; +}; + +const struct GNUNET_CONFIGURATION_Handle *cfg; + +struct RequestHandle +{ + /** + * Handle to Credential service. + */ + struct GNUNET_CREDENTIAL_Handle *credential; + + /** + * Handle to lookup request + */ + struct GNUNET_CREDENTIAL_Request *verify_request; + + /** + * Handle to issue request + */ + struct GNUNET_CREDENTIAL_Request *issue_request; + + /** + * Handle to identity + */ + struct GNUNET_IDENTITY_Handle *identity; + + /** + * Handle to identity operation + */ + struct GNUNET_IDENTITY_Operation *id_op; + + /** + * Handle to ego lookup + */ + struct GNUNET_IDENTITY_EgoLookup *ego_lookup; + + /** + * Handle to rest request + */ + struct GNUNET_REST_RequestHandle *rest_handle; + + /** + * ID of a task associated with the resolution process. + */ + struct GNUNET_SCHEDULER_Task *timeout_task; + + /** + * The root of the received JSON or NULL + */ + json_t *json_root; + + /** + * The plugin result processor + */ + GNUNET_REST_ResultProcessor proc; + + /** + * The closure of the result processor + */ + void *proc_cls; + + /** + * The issuer attribute to verify + */ + char *issuer_attr; + + /** + * The subject attribute + */ + char *subject_attr; + + /** + * The public key of the issuer + */ + struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key; + + /** + * The public key of the subject + */ + struct GNUNET_CRYPTO_EcdsaPublicKey subject_key; + + /** + * HTTP response code + */ + int response_code; + + /** + * Timeout + */ + struct GNUNET_TIME_Relative timeout; +}; + + +/** + * Cleanup lookup handle. + * + * @param handle Handle to clean up + */ +static void +cleanup_handle (struct RequestHandle *handle) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Cleaning up\n"); + if (NULL != handle->json_root) + json_decref (handle->json_root); + + if (NULL != handle->issuer_attr) + GNUNET_free (handle->issuer_attr); + if (NULL != handle->subject_attr) + GNUNET_free (handle->subject_attr); + if (NULL != handle->verify_request) + GNUNET_CREDENTIAL_request_cancel (handle->verify_request); + if (NULL != handle->credential) + GNUNET_CREDENTIAL_disconnect (handle->credential); + if (NULL != handle->id_op) + GNUNET_IDENTITY_cancel (handle->id_op); + if (NULL != handle->ego_lookup) + GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup); + if (NULL != handle->identity) + GNUNET_IDENTITY_disconnect (handle->identity); + if (NULL != handle->timeout_task) + { + GNUNET_SCHEDULER_cancel (handle->timeout_task); + } + GNUNET_free (handle); +} + + +static void +do_error (void *cls) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + + resp = GNUNET_REST_create_response (NULL); + handle->proc (handle->proc_cls, resp, handle->response_code); + cleanup_handle (handle); +} + +/** + * Attribute delegation to JSON + * + * @param delegation_chain_entry the DSE + * @return JSON, NULL if failed + */ +static json_t* +attribute_delegation_to_json (struct + GNUNET_CREDENTIAL_Delegation * + delegation_chain_entry) +{ + char *subject; + char *issuer; + json_t *attr_obj; + + issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string ( + &delegation_chain_entry->issuer_key); + if (NULL == issuer) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Issuer in delegation malformed\n"); + return NULL; + } + subject = GNUNET_CRYPTO_ecdsa_public_key_to_string ( + &delegation_chain_entry->subject_key); + if (NULL == subject) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Subject in credential malformed\n"); + GNUNET_free (issuer); + return NULL; + } + attr_obj = json_object (); + + json_object_set_new (attr_obj, "issuer", json_string (issuer)); + json_object_set_new (attr_obj, "issuer_attribute", + json_string (delegation_chain_entry->issuer_attribute)); + + json_object_set_new (attr_obj, "subject", json_string (subject)); + if (0 < delegation_chain_entry->subject_attribute_len) + { + json_object_set_new (attr_obj, "subject_attribute", + json_string ( + delegation_chain_entry->subject_attribute)); + } + GNUNET_free (issuer); + GNUNET_free (subject); + return attr_obj; +} + +/** + * JSONAPI resource to Credential + * + * @param res the JSONAPI resource + * @return the resulting credential, NULL if failed + */ +static struct GNUNET_CREDENTIAL_Credential* +json_to_credential (json_t *res) +{ + struct GNUNET_CREDENTIAL_Credential *cred; + json_t *tmp; + const char *attribute; + const char *signature; + char *sig; + + tmp = json_object_get (res, "attribute"); + if (0 == json_is_string (tmp)) + { + return NULL; + } + attribute = json_string_value (tmp); + cred = GNUNET_malloc (sizeof(struct GNUNET_CREDENTIAL_Credential) + + strlen (attribute)); + cred->issuer_attribute = attribute; + cred->issuer_attribute_len = strlen (attribute); + tmp = json_object_get (res, "issuer"); + if (0 == json_is_string (tmp)) + { + GNUNET_free (cred); + return NULL; + } + + GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value (tmp), + strlen (json_string_value (tmp)), + &cred->issuer_key); + tmp = json_object_get (res, "subject"); + if (0 == json_is_string (tmp)) + { + GNUNET_free (cred); + return NULL; + } + GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value (tmp), + strlen (json_string_value (tmp)), + &cred->subject_key); + + tmp = json_object_get (res, "signature"); + if (0 == json_is_string (tmp)) + { + GNUNET_free (cred); + return NULL; + } + signature = json_string_value (tmp); + GNUNET_STRINGS_base64_decode (signature, + strlen (signature), + (char**) &sig); + GNUNET_memcpy (&cred->signature, + sig, + sizeof(struct GNUNET_CRYPTO_EcdsaSignature)); + GNUNET_free (sig); + + tmp = json_object_get (res, "expiration"); + if (0 == json_is_integer (tmp)) + { + GNUNET_free (cred); + return NULL; + } + cred->expiration.abs_value_us = json_integer_value (tmp); + return cred; +} + + +/** + * Credential to JSON + * + * @param cred the credential + * @return the resulting json, NULL if failed + */ +static json_t* +credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred) +{ + char *issuer; + char *subject; + char *signature; + char attribute[cred->issuer_attribute_len + 1]; + json_t *cred_obj; + + issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key); + if (NULL == issuer) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Issuer in credential malformed\n"); + return NULL; + } + subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key); + if (NULL == subject) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Subject in credential malformed\n"); + GNUNET_free (issuer); + return NULL; + } + GNUNET_STRINGS_base64_encode ((char*) &cred->signature, + sizeof(struct GNUNET_CRYPTO_EcdsaSignature), + &signature); + GNUNET_memcpy (attribute, + cred->issuer_attribute, + cred->issuer_attribute_len); + attribute[cred->issuer_attribute_len] = '\0'; + cred_obj = json_object (); + json_object_set_new (cred_obj, "issuer", json_string (issuer)); + json_object_set_new (cred_obj, "subject", json_string (subject)); + json_object_set_new (cred_obj, "attribute", json_string (attribute)); + json_object_set_new (cred_obj, "signature", json_string (signature)); + json_object_set_new (cred_obj, "expiration", json_integer ( + cred->expiration.abs_value_us)); + GNUNET_free (issuer); + GNUNET_free (subject); + GNUNET_free (signature); + return cred_obj; +} + +static void +handle_collect_response (void *cls, + unsigned int d_count, + struct GNUNET_CREDENTIAL_Delegation *delegation_chain, + unsigned int c_count, + struct GNUNET_CREDENTIAL_Credential *cred) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + struct GNUNET_JSONAPI_Document *json_document; + struct GNUNET_JSONAPI_Resource *json_resource; + json_t *cred_obj; + json_t *cred_array; + char *result; + char *issuer; + char *id; + uint32_t i; + + handle->verify_request = NULL; + if (NULL == cred) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Verify failed.\n"); + handle->response_code = MHD_HTTP_NOT_FOUND; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key); + if (NULL == issuer) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Issuer in delegation malformed\n"); + return; + } + GNUNET_asprintf (&id, + "%s.%s", + issuer, + handle->issuer_attr); + GNUNET_free (issuer); + json_document = GNUNET_JSONAPI_document_new (); + json_resource = GNUNET_JSONAPI_resource_new ( + GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO, + id); + GNUNET_free (id); + cred_array = json_array (); + for (i = 0; i < c_count; i++) + { + cred_obj = credential_to_json (&cred[i]); + json_array_append_new (cred_array, cred_obj); + } + GNUNET_JSONAPI_resource_add_attr (json_resource, + GNUNET_REST_JSONAPI_CREDENTIAL, + cred_array); + GNUNET_JSONAPI_document_resource_add (json_document, json_resource); + GNUNET_JSONAPI_document_serialize (json_document, &result); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Result %s\n", + result); + json_decref (cred_array); + GNUNET_JSONAPI_document_delete (json_document); + resp = GNUNET_REST_create_response (result); + GNUNET_free (result); + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + cleanup_handle (handle); +} + +static void +subject_ego_lookup (void *cls, + const struct GNUNET_IDENTITY_Ego *ego) +{ + struct RequestHandle *handle = cls; + const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key; + + handle->ego_lookup = NULL; + + if (NULL == ego) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Subject not found\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + sub_key = GNUNET_IDENTITY_ego_get_private_key (ego); + handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential, + &handle->issuer_key, + handle->issuer_attr, + sub_key, + &handle_collect_response, + handle); +} + + + +static void +handle_verify_response (void *cls, + unsigned int d_count, + struct GNUNET_CREDENTIAL_Delegation *delegation_chain, + unsigned int c_count, + struct GNUNET_CREDENTIAL_Credential *cred) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + struct GNUNET_JSONAPI_Document *json_document; + struct GNUNET_JSONAPI_Resource *json_resource; + json_t *cred_obj; + json_t *attr_obj; + json_t *cred_array; + json_t *attr_array; + char *result; + char *issuer; + char *id; + uint32_t i; + + handle->verify_request = NULL; + if (NULL == cred) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Verify failed.\n"); + handle->response_code = MHD_HTTP_NOT_FOUND; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key); + if (NULL == issuer) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Issuer in delegation malformed\n"); + return; + } + GNUNET_asprintf (&id, + "%s.%s", + issuer, + handle->issuer_attr); + GNUNET_free (issuer); + json_document = GNUNET_JSONAPI_document_new (); + json_resource = GNUNET_JSONAPI_resource_new ( + GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO, + id); + GNUNET_free (id); + attr_array = json_array (); + for (i = 0; i < d_count; i++) + { + attr_obj = attribute_delegation_to_json (&delegation_chain[i]); + json_array_append_new (attr_array, attr_obj); + } + cred_array = json_array (); + for (i = 0; i < c_count; i++) + { + cred_obj = credential_to_json (&cred[i]); + json_array_append_new (cred_array, cred_obj); + } + GNUNET_JSONAPI_resource_add_attr (json_resource, + GNUNET_REST_JSONAPI_CREDENTIAL, + cred_array); + GNUNET_JSONAPI_resource_add_attr (json_resource, + GNUNET_REST_JSONAPI_DELEGATIONS, + attr_array); + GNUNET_JSONAPI_document_resource_add (json_document, json_resource); + GNUNET_JSONAPI_document_serialize (json_document, &result); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Result %s\n", + result); + json_decref (attr_array); + json_decref (cred_array); + GNUNET_JSONAPI_document_delete (json_document); + resp = GNUNET_REST_create_response (result); + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + GNUNET_free (result); + cleanup_handle (handle); +} + +static void +collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle, + const char*url, + void *cls) +{ + struct RequestHandle *handle = cls; + struct GNUNET_HashCode key; + char *tmp; + char *entity_attr; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Connecting...\n"); + handle->credential = GNUNET_CREDENTIAL_connect (cfg); + handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, + &do_error, handle); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Connected\n"); + if (NULL == handle->credential) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Connecting to CREDENTIAL failed\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR, + strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR), + &key); + if (GNUNET_NO == + GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, + &key)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Missing issuer attribute\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, + &key); + entity_attr = GNUNET_strdup (tmp); + tmp = strtok (entity_attr, "."); + if (NULL == tmp) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Malformed issuer or attribute\n"); + GNUNET_free (entity_attr); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp, + strlen (tmp), + &handle->issuer_key)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Malformed issuer key\n"); + GNUNET_free (entity_attr); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + tmp = strtok (NULL, "."); // Issuer attribute + if (NULL == tmp) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Malformed attribute\n"); + GNUNET_free (entity_attr); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->issuer_attr = GNUNET_strdup (tmp); + GNUNET_free (entity_attr); + + GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO, + strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO), + &key); + if (GNUNET_NO == + GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, + &key)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Missing subject\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, + &key); + if (NULL == tmp) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Malformed subject\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg, + tmp, + &subject_ego_lookup, + handle); +} + + + +static void +verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle, + const char*url, + void *cls) +{ + struct RequestHandle *handle = cls; + struct GNUNET_HashCode key; + struct GNUNET_JSONAPI_Document *json_obj; + struct GNUNET_JSONAPI_Resource *res; + struct GNUNET_CREDENTIAL_Credential *cred; + char *tmp; + char *entity_attr; + int i; + uint32_t credential_count; + uint32_t resource_count; + json_t *cred_json; + json_t *data_js; + json_error_t err; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Connecting...\n"); + handle->credential = GNUNET_CREDENTIAL_connect (cfg); + handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, + &do_error, handle); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Connected\n"); + if (NULL == handle->credential) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Connecting to CREDENTIAL failed\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR, + strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR), + &key); + if (GNUNET_NO == + GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, + &key)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Missing issuer attribute\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, + &key); + entity_attr = GNUNET_strdup (tmp); + tmp = strtok (entity_attr, "."); + if (NULL == tmp) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Malformed issuer or attribute\n"); + GNUNET_free (entity_attr); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp, + strlen (tmp), + &handle->issuer_key)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Malformed issuer key\n"); + GNUNET_free (entity_attr); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + tmp = strtok (NULL, "."); // Issuer attribute + if (NULL == tmp) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Malformed attribute\n"); + GNUNET_free (entity_attr); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->issuer_attr = GNUNET_strdup (tmp); + GNUNET_free (entity_attr); + + GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY, + strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY), + &key); + if (GNUNET_NO == + GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, + &key)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Missing subject key\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, + &key); + if (NULL == tmp) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Malformed subject\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp, + strlen (tmp), + &handle->subject_key)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Malformed subject key\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + if (0 >= handle->rest_handle->data_size) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Missing credentials\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + struct GNUNET_JSON_Specification docspec[] = { + GNUNET_JSON_spec_jsonapi_document (&json_obj), + GNUNET_JSON_spec_end () + }; + char term_data[handle->rest_handle->data_size + 1]; + term_data[handle->rest_handle->data_size] = '\0'; + credential_count = 0; + GNUNET_memcpy (term_data, + handle->rest_handle->data, + handle->rest_handle->data_size); + data_js = json_loads (term_data, + JSON_DECODE_ANY, + &err); + GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec, + NULL, NULL)); + json_decref (data_js); + if (NULL == json_obj) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to parse JSONAPI Object from %s\n", + term_data); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + resource_count = GNUNET_JSONAPI_document_resource_count (json_obj); + GNUNET_assert (1 == resource_count); + res = (GNUNET_JSONAPI_document_get_resource (json_obj, 0)); + if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (res, + GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Resource not a credential!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to parse JSONAPI Object from %s\n", + term_data); + GNUNET_JSONAPI_document_delete (json_obj); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + cred_json = GNUNET_JSONAPI_resource_read_attr (res, + GNUNET_REST_JSONAPI_CREDENTIAL); + + GNUNET_assert (json_is_array (cred_json)); + + credential_count = json_array_size (cred_json); + + struct GNUNET_CREDENTIAL_Credential credentials[credential_count]; + for (i = 0; i < credential_count; i++) + { + cred = json_to_credential (json_array_get (cred_json, i)); + if (NULL == cred) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to parse credential!\n"); + continue; + } + GNUNET_memcpy (&credentials[i], + cred, + sizeof(struct GNUNET_CREDENTIAL_Credential)); + credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute); + GNUNET_free (cred); + } + GNUNET_JSONAPI_document_delete (json_obj); + handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential, + &handle->issuer_key, + handle->issuer_attr, + &handle->subject_key, + credential_count, + credentials, + &handle_verify_response, + handle); + for (i = 0; i < credential_count; i++) + GNUNET_free ((char*) credentials[i].issuer_attribute); +} + +void +send_cred_response (struct RequestHandle *handle, + struct GNUNET_CREDENTIAL_Credential *cred) +{ + struct MHD_Response *resp; + struct GNUNET_JSONAPI_Document *json_document; + struct GNUNET_JSONAPI_Resource *json_resource; + json_t *cred_obj; + char *result; + char *issuer; + char *subject; + char *signature; + char *id; + + GNUNET_assert (NULL != cred); + issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key); + if (NULL == issuer) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Subject malformed\n"); + GNUNET_free (issuer); + return; + } + GNUNET_asprintf (&id, + "%s.%s", + issuer, + (char*) &cred[1]); + subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key); + if (NULL == subject) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Subject malformed\n"); + GNUNET_free (id); + GNUNET_free (issuer); + return; + } + GNUNET_STRINGS_base64_encode ((char*) &cred->signature, + sizeof(struct GNUNET_CRYPTO_EcdsaSignature), + &signature); + json_document = GNUNET_JSONAPI_document_new (); + json_resource = GNUNET_JSONAPI_resource_new ( + GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO, + id); + GNUNET_free (id); + cred_obj = json_object (); + json_object_set_new (cred_obj, "issuer", json_string (issuer)); + json_object_set_new (cred_obj, "subject", json_string (subject)); + json_object_set_new (cred_obj, "expiration", json_integer ( + cred->expiration.abs_value_us)); + json_object_set_new (cred_obj, "signature", json_string (signature)); + GNUNET_JSONAPI_resource_add_attr (json_resource, + GNUNET_REST_JSONAPI_CREDENTIAL, + cred_obj); + GNUNET_JSONAPI_document_resource_add (json_document, json_resource); + GNUNET_JSONAPI_document_serialize (json_document, &result); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Result %s\n", + result); + json_decref (cred_obj); + GNUNET_JSONAPI_document_delete (json_document); + resp = GNUNET_REST_create_response (result); + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + GNUNET_free (result); + GNUNET_free (signature); + GNUNET_free (issuer); + GNUNET_free (subject); + cleanup_handle (handle); +} + +void +get_cred_issuer_cb (void *cls, + struct GNUNET_IDENTITY_Ego *ego, + void **ctx, + const char *name) +{ + struct RequestHandle *handle = cls; + struct GNUNET_TIME_Absolute etime_abs; + struct GNUNET_TIME_Relative etime_rel; + const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key; + struct GNUNET_HashCode key; + struct GNUNET_CREDENTIAL_Credential *cred; + char*expiration_str; + char*tmp; + + handle->id_op = NULL; + + if (NULL == name) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Issuer not configured!\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Connecting to credential service...\n"); + handle->credential = GNUNET_CREDENTIAL_connect (cfg); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Connected\n"); + if (NULL == handle->credential) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Connecting to CREDENTIAL failed\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION, + strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION), + &key); + if (GNUNET_NO == + GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->url_param_map, + &key)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Missing expiration\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + expiration_str = GNUNET_CONTAINER_multihashmap_get ( + handle->rest_handle->url_param_map, + &key); + if (NULL == expiration_str) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Expiration malformed\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str, + &etime_rel)) + { + etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel); + } + else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str, + &etime_abs)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Malformed expiration: %s\n", expiration_str); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR, + strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR), + &key); + if (GNUNET_NO == + GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->url_param_map, + &key)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Missing issuer attribute\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->issuer_attr = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get + (handle->rest_handle->url_param_map, + &key)); + GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY, + strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY), + &key); + if (GNUNET_NO == + GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->url_param_map, + &key)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Missing subject\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, + &key); + if (NULL == tmp) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Malformed subject\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp, + strlen (tmp), + &handle->subject_key)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Malformed subject key\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego); + cred = GNUNET_CREDENTIAL_credential_issue (issuer_key, + &handle->subject_key, + handle->issuer_attr, + &etime_abs); + if (NULL == cred) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to create credential\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + send_cred_response (handle, cred); +} + + +static void +issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle, + const char*url, + void *cls) +{ + struct RequestHandle *handle = cls; + + handle->identity = GNUNET_IDENTITY_connect (cfg, + NULL, + NULL); + handle->id_op = GNUNET_IDENTITY_get (handle->identity, + "credential-issuer", + &get_cred_issuer_cb, + handle); + handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, + &do_error, + handle); +} + +static void +options_cont (struct GNUNET_REST_RequestHandle *con_handle, + const char*url, + void *cls) +{ + struct MHD_Response *resp; + struct RequestHandle *handle = cls; + + // For GNS, independent of path return all options + resp = GNUNET_REST_create_response (NULL); + MHD_add_response_header (resp, + "Access-Control-Allow-Methods", + MHD_HTTP_METHOD_GET); + handle->proc (handle->proc_cls, + resp, + MHD_HTTP_OK); + cleanup_handle (handle); +} + + +static void +rest_credential_process_request (struct + GNUNET_REST_RequestHandle *conndata_handle, + GNUNET_REST_ResultProcessor proc, + void *proc_cls) +{ + struct RequestHandle *handle = GNUNET_new (struct RequestHandle); + struct GNUNET_REST_RequestHandlerError err; + + handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; + handle->proc_cls = proc_cls; + handle->proc = proc; + handle->rest_handle = conndata_handle; + + static const struct GNUNET_REST_RequestHandler handlers[] = { + { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, + &verify_cred_cont }, + { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, + &collect_cred_cont }, + { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, + &issue_cred_cont }, + { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont }, + GNUNET_REST_HANDLER_END + }; + + if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle, + handlers, + &err, + handle)) + { + handle->response_code = err.error_code; + GNUNET_SCHEDULER_add_now (&do_error, handle); + } +} + + +/** + * Entry point for the plugin. + * + * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" + * @return NULL on error, otherwise the plugin context + */ +void * +libgnunet_plugin_rest_credential_init (void *cls) +{ + static struct Plugin plugin; + + cfg = cls; + struct GNUNET_REST_Plugin *api; + + if (NULL != plugin.cfg) + return NULL; /* can only initialize once! */ + memset (&plugin, 0, sizeof(struct Plugin)); + plugin.cfg = cfg; + api = GNUNET_new (struct GNUNET_REST_Plugin); + api->cls = &plugin; + api->name = GNUNET_REST_API_NS_CREDENTIAL; + api->process_request = &rest_credential_process_request; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _ ("GNS REST API initialized\n")); + return api; +} + + +/** + * Exit point from the plugin. + * + * @param cls the plugin context (as returned by "init") + * @return always NULL + */ +void * +libgnunet_plugin_rest_credential_done (void *cls) +{ + struct GNUNET_REST_Plugin *api = cls; + struct Plugin *plugin = api->cls; + + plugin->cfg = NULL; + GNUNET_free (api); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS REST plugin is finished\n"); + return NULL; +} + +/* end of plugin_rest_gns.c */ diff --git a/src/abd/test_abd_bi_and.sh b/src/abd/test_abd_bi_and.sh new file mode 100755 index 000000000..b32313636 --- /dev/null +++ b/src/abd/test_abd_bi_and.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f` + + + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10" +gnunet-arm -s -c test_abd_lookup.conf + +gnunet-identity -C a -c test_abd_lookup.conf +gnunet-identity -C b -c test_abd_lookup.conf +gnunet-identity -C c -c test_abd_lookup.conf +gnunet-identity -C d -c test_abd_lookup.conf +gnunet-identity -C e -c test_abd_lookup.conf +gnunet-identity -C f -c test_abd_lookup.conf +gnunet-identity -C g -c test_abd_lookup.conf +gnunet-identity -C h -c test_abd_lookup.conf +AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}') +BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}') +CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}') +DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}') +EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}') +FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}') +GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}') +HKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep h | awk '{print $3}') +gnunet-identity -d + +# (1) (A.a) <- B.b +# (2) (B.b) <- C.c AND G.g +# (3) C.c <- (D.D) +# (4) D.d <- (E.e) +# (5) E.e <- (F) priv +# (6) (G.g) <- H.h +# (7) H.h <- (F) priv + +# BIDIRECTIONAL +gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z a +gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$CKEY c, $GKEY g" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z b +gnunet-abd --createIssuerSide --ego=g --attribute="g" --subject="$HKEY h" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z b + +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=d --import="$SIGNED" +gnunet-namestore -D -z d +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=e --import="$SIGNED" +gnunet-namestore -D -z e +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private +gnunet-namestore -D -z f +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=h --attribute="h" --subject="$FKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private +gnunet-namestore -D -z h + +# Starting to resolve +echo "+++ Starting to Resolve +++" + +DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=f --forward --backward -c test_abd_lookup.conf | paste -d, -s - -` +echo $DELS +echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate=\'$DELS\' --forward --backward -c test_abd_lookup.conf +gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate="$DELS" --forward --backward -c test_abd_lookup.conf + +RES=$? + +# Cleanup properly +gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z g -d -n "g" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf + +gnunet-arm -e -c test_abd_lookup.conf + +if [ "$RES" == 0 ] +then + exit 0 +else + echo "FAIL: Failed to verify credential." + exit 1 +fi + diff --git a/src/abd/test_abd_bi_and2.sh b/src/abd/test_abd_bi_and2.sh new file mode 100755 index 000000000..8d1601ef4 --- /dev/null +++ b/src/abd/test_abd_bi_and2.sh @@ -0,0 +1,94 @@ +#!/usr/bin/env bash +trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f` + + + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10" +gnunet-arm -s -c test_abd_lookup.conf + +gnunet-identity -C a -c test_abd_lookup.conf +gnunet-identity -C b -c test_abd_lookup.conf +gnunet-identity -C c -c test_abd_lookup.conf +gnunet-identity -C d -c test_abd_lookup.conf +gnunet-identity -C e -c test_abd_lookup.conf +gnunet-identity -C f -c test_abd_lookup.conf +gnunet-identity -C g -c test_abd_lookup.conf +gnunet-identity -C h -c test_abd_lookup.conf +AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}') +BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}') +CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}') +DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}') +EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}') +FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}') +GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}') +HKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep h | awk '{print $3}') +gnunet-identity -d + +# (1) (A.a) <- B.b +# (2) (B.b) <- C.c AND G.g +# (3) C.c <- (D.D) +# (4) D.d <- (E.e) +# (5) E.e <- (F) priv +# (6) G.g <- (F) priv + +# BIDIRECTIONAL +gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z a +gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$CKEY c, $GKEY g" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z b + +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=d --import="$SIGNED" +gnunet-namestore -D -z d +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=e --import="$SIGNED" +gnunet-namestore -D -z e +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private +gnunet-namestore -D -z f +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=g --attribute="g" --subject="$FKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private +gnunet-namestore -D -z h + +# Starting to resolve +echo "+++ Starting to Resolve +++" + +DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=f -c test_abd_lookup.conf | paste -d, -s - -` +echo $DELS +echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate=\'$DELS\' -c test_abd_lookup.conf +gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate="$DELS" -c test_abd_lookup.conf + +RES=$? + +# Cleanup properly +gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf + +gnunet-arm -e -c test_abd_lookup.conf + +if [ "$RES" == 0 ] +then + exit 0 +else + echo "FAIL: Failed to verify credential." + exit 1 +fi + diff --git a/src/abd/test_abd_bi_and3.sh b/src/abd/test_abd_bi_and3.sh new file mode 100755 index 000000000..cde2a020b --- /dev/null +++ b/src/abd/test_abd_bi_and3.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash +trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f` + + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10" +gnunet-arm -s -c test_abd_lookup.conf + +gnunet-identity -C a -c test_abd_lookup.conf +gnunet-identity -C b -c test_abd_lookup.conf +gnunet-identity -C c -c test_abd_lookup.conf +gnunet-identity -C d -c test_abd_lookup.conf +gnunet-identity -C e -c test_abd_lookup.conf +gnunet-identity -C f -c test_abd_lookup.conf +gnunet-identity -C g -c test_abd_lookup.conf +gnunet-identity -C h -c test_abd_lookup.conf +AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}') +BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}') +CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}') +DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}') +EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}') +FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}') +GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}') +HKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep h | awk '{print $3}') +gnunet-identity -d + +# (1) (A.a) <- B.b +# (2) (B.b) <- C.c AND G.g +# (3) C.c <- (D.d) +# (4) D.d <- (E.e) +# (5) E.e <- (F) priv +# (6) G.g <- (H.h) +# (7) H.h <- (F) priv + +# BIDIRECTIONAL +gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z a +gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$CKEY c, $GKEY g" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z b + +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=d --import="$SIGNED" +gnunet-namestore -D -z d +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=e --import="$SIGNED" +gnunet-namestore -D -z e +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=g --attribute="g" --subject="$HKEY h" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=h --import="$SIGNED" +gnunet-namestore -D -z h +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=h --attribute="h" --subject="$FKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private +gnunet-namestore -D -z f + +# Starting to resolve +echo "+++ Starting to Resolve +++" + +DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=f -c test_abd_lookup.conf | paste -d, -s - -` +echo $DELS +echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate=\'$DELS\' -c test_abd_lookup.conf +gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate="$DELS" -c test_abd_lookup.conf + +RES=$? + +# Cleanup properly +gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z h -d -n "@" -t DEL -c test_abd_lookup.conf + +gnunet-arm -e -c test_abd_lookup.conf + +if [ "$RES" == 0 ] +then + exit 0 +else + echo "FAIL: Failed to verify credential." + exit 1 +fi diff --git a/src/abd/test_abd_bi_and4.sh b/src/abd/test_abd_bi_and4.sh new file mode 100755 index 000000000..e8cd6efd6 --- /dev/null +++ b/src/abd/test_abd_bi_and4.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f` + + + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10" +gnunet-arm -s -c test_abd_lookup.conf + +gnunet-identity -C a -c test_abd_lookup.conf +gnunet-identity -C b -c test_abd_lookup.conf +gnunet-identity -C c -c test_abd_lookup.conf +gnunet-identity -C d -c test_abd_lookup.conf +gnunet-identity -C e -c test_abd_lookup.conf +gnunet-identity -C f -c test_abd_lookup.conf +gnunet-identity -C g -c test_abd_lookup.conf +gnunet-identity -C h -c test_abd_lookup.conf +AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}') +BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}') +CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}') +DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}') +EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}') +FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}') +GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}') +HKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep h | awk '{print $3}') +gnunet-identity -d + +# (1) (A.a) <- B.b +# (2) (B.b) <- C.c AND G.g +# (3) C.c <- (F) priv +# (4) G.g <- (F) priv + +# BIDIRECTIONAL +gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z a +gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$CKEY c, $GKEY g" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z b + +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=g --attribute="g" --subject="$FKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$FKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private +gnunet-namestore -D -z f + +# Starting to resolve +echo "+++ Starting to Resolve +++" + +DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=f --backward -c test_abd_lookup.conf | paste -d, -s - -` +echo $DELS +echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate=\'$DELS\' --backward -c test_abd_lookup.conf +gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate="$DELS" --backward -c test_abd_lookup.conf + +RES=$? + +# Cleanup properly +gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf + +gnunet-arm -e -c test_abd_lookup.conf + +if [ "$RES" == 0 ] +then + exit 0 +else + echo "FAIL: Failed to verify credential." + exit 1 +fi + diff --git a/src/abd/test_abd_bi_bw.sh b/src/abd/test_abd_bi_bw.sh new file mode 100755 index 000000000..6b0e51722 --- /dev/null +++ b/src/abd/test_abd_bi_bw.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f` + + + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10" +gnunet-arm -s -c test_abd_lookup.conf + +gnunet-identity -C a -c test_abd_lookup.conf +gnunet-identity -C b -c test_abd_lookup.conf +gnunet-identity -C c -c test_abd_lookup.conf +gnunet-identity -C d -c test_abd_lookup.conf +gnunet-identity -C e -c test_abd_lookup.conf +gnunet-identity -C f -c test_abd_lookup.conf +gnunet-identity -C g -c test_abd_lookup.conf +AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}') +BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}') +CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}') +DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}') +EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}') +FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}') +GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}') +gnunet-identity -d + +# (1) (A.a) <- B.b +# (2) (B.b) <- C.c +# (3) C.c <- (D.D) +# (4) D.d <- (E.e) +# (5) E.e <- (F) + +# BIDIRECTIONAL +gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z a +gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$CKEY c" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z b + +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=d --import="$SIGNED" +gnunet-namestore -D -z d +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=e --import="$SIGNED" +gnunet-namestore -D -z e +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private +gnunet-namestore -D -z f + +# Starting to resolve +echo "+++ Starting to Resolve +++" + +DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=f --forward --backward -c test_abd_lookup.conf | paste -d, -s - -` +echo $DELS +echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate=\'$DELS\' --forward --backward -c test_abd_lookup.conf +gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate="$DELS" --forward --backward -c test_abd_lookup.conf + +RES=$? + +# Cleanup properly +gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf + +gnunet-arm -e -c test_abd_lookup.conf + +if [ "$RES" == 0 ] +then + exit 0 +else + echo "FAIL: Failed to verify credential." + exit 1 +fi diff --git a/src/abd/test_abd_bi_bw_link.sh b/src/abd/test_abd_bi_bw_link.sh new file mode 100755 index 000000000..f60f78827 --- /dev/null +++ b/src/abd/test_abd_bi_bw_link.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f` + + + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10" +gnunet-arm -s -c test_abd_lookup.conf + +gnunet-identity -C a -c test_abd_lookup.conf +gnunet-identity -C b -c test_abd_lookup.conf +gnunet-identity -C c -c test_abd_lookup.conf +gnunet-identity -C d -c test_abd_lookup.conf +gnunet-identity -C e -c test_abd_lookup.conf +gnunet-identity -C f -c test_abd_lookup.conf +gnunet-identity -C g -c test_abd_lookup.conf +AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}') +BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}') +CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}') +DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}') +EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}') +FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}') +GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}') +gnunet-identity -d + +# (1) (A.a) <- B.b +# (2) (B.b) <- G.g.c +# (3) (G.g) <- C +# (3) C.c <- (D.D) +# (4) D.d <- (E.e) +# (5) E.e <- (F) + +# BIDIRECTIONAL +gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z a +gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$GKEY g.c" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z b +gnunet-abd --createIssuerSide --ego=g --attribute="g" --subject="$CKEY" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z b + +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=d --import="$SIGNED" +gnunet-namestore -D -z d +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=e --import="$SIGNED" +gnunet-namestore -D -z e +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private +gnunet-namestore -D -z f + +# Starting to resolve +echo "+++ Starting to Resolve +++" + +DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=f --forward --backward -c test_abd_lookup.conf | paste -d, -s - -` +echo $DELS +echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate=\'$DELS\' --forward --backward -c test_abd_lookup.conf +gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate="$DELS" --forward --backward -c test_abd_lookup.conf + +RES=$? + +# Cleanup properly +gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z g -d -n "g" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf + +gnunet-arm -e -c test_abd_lookup.conf + +if [ "$RES" == 0 ] +then + exit 0 +else + echo "FAIL: Failed to verify credential." + exit 1 +fi + diff --git a/src/abd/test_abd_bi_bw_link2.sh b/src/abd/test_abd_bi_bw_link2.sh new file mode 100755 index 000000000..b0fb49b8e --- /dev/null +++ b/src/abd/test_abd_bi_bw_link2.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash +trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f` + + + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10" +gnunet-arm -s -c test_abd_lookup.conf + +gnunet-identity -C a -c test_abd_lookup.conf +gnunet-identity -C b -c test_abd_lookup.conf +gnunet-identity -C c -c test_abd_lookup.conf +gnunet-identity -C d -c test_abd_lookup.conf +gnunet-identity -C e -c test_abd_lookup.conf +gnunet-identity -C f -c test_abd_lookup.conf +gnunet-identity -C g -c test_abd_lookup.conf +AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}') +BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}') +CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}') +DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}') +EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}') +FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}') +GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}') +gnunet-identity -d + +# (1) (A.a) <- B.b +# (2) (B.b) <- G.g.c +# (3) G.g <- (C) +# (3) C.c <- (D.d) +# (4) D.d <- (E.e) +# (5) E.e <- (F) + +# BIDIRECTIONAL +gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z a +gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$GKEY g.c" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z b + +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=g --attribute="g" --subject="$CKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=c --import="$SIGNED" +gnunet-namestore -D -z c +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=d --import="$SIGNED" +gnunet-namestore -D -z d +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=e --import="$SIGNED" +gnunet-namestore -D -z e +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private +gnunet-namestore -D -z f + +# Starting to resolve +echo "+++ Starting to Resolve +++" + +DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=f --forward --backward -c test_abd_lookup.conf | paste -d, -s - -` +echo $DELS +echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate=\'$DELS\' --forward --backward -c test_abd_lookup.conf +gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate="$DELS" --forward --backward -c test_abd_lookup.conf + +RES=$? + +# Cleanup properly +gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z c -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf + +gnunet-arm -e -c test_abd_lookup.conf + +if [ "$RES" == 0 ] +then + exit 0 +else + echo "FAIL: Failed to verify credential." + exit 1 +fi + diff --git a/src/abd/test_abd_bi_fw.sh b/src/abd/test_abd_bi_fw.sh new file mode 100755 index 000000000..75a940fbe --- /dev/null +++ b/src/abd/test_abd_bi_fw.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f` + + + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10" +gnunet-arm -s -c test_abd_lookup.conf + +gnunet-identity -C a -c test_abd_lookup.conf +gnunet-identity -C b -c test_abd_lookup.conf +gnunet-identity -C c -c test_abd_lookup.conf +gnunet-identity -C d -c test_abd_lookup.conf +gnunet-identity -C e -c test_abd_lookup.conf +gnunet-identity -C f -c test_abd_lookup.conf +gnunet-identity -C g -c test_abd_lookup.conf +AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}') +BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}') +CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}') +DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}') +EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}') +FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}') +GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}') +gnunet-identity -d + +# (1) (A.a) <- B.b +# (2) (B.b) <- C.c +# (3) C.c <- (D.D) +# (4) D.d <- (E.e) +# (5) E.e <- (F.f) +# (6) F.f <- (G) + +# BIDIRECTIONAL +gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z a +gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$CKEY c" --ttl=5m -c test_abd_lookup.conf +gnunet-namestore -D -z b + +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=d --import="$SIGNED" +gnunet-namestore -D -z d +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=e --import="$SIGNED" +gnunet-namestore -D -z e +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY f" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" +gnunet-namestore -D -z f +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=f --attribute="f" --subject="$GKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=g --import="$SIGNED" --private +gnunet-namestore -D -z g + +# Starting to resolve +echo "+++ Starting to Resolve +++" + +DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=g --forward --backward -c test_abd_lookup.conf | paste -d, -s - -` +echo $DELS +echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$GKEY --delegate=\'$DELS\' --forward --backward -c test_abd_lookup.conf +gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$GKEY --delegate="$DELS" --forward --backward -c test_abd_lookup.conf + +RES=$? + +# Cleanup properly +gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z g -d -n "@" -t DEL -c test_abd_lookup.conf + +gnunet-arm -e -c test_abd_lookup.conf + +if [ "$RES" == 0 ] +then + exit 0 +else + echo "FAIL: Failed to verify credential." + exit 1 +fi diff --git a/src/abd/test_abd_defaults.conf b/src/abd/test_abd_defaults.conf new file mode 100644 index 000000000..7b4cb576d --- /dev/null +++ b/src/abd/test_abd_defaults.conf @@ -0,0 +1,24 @@ +@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf + +[PATHS] +GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-abd-testing/ + +[namestore-sqlite] +FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db + +[namecache-sqlite] +FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db + +[identity] +# Directory where we store information about our egos +EGODIR = $GNUNET_TEST_HOME/identity/egos/ + +[dhtcache] +DATABASE = heap + +[transport] +PLUGINS = tcp + +[transport-tcp] +BINDTO = 127.0.0.1 + diff --git a/src/abd/test_abd_issue.sh b/src/abd/test_abd_issue.sh new file mode 100755 index 000000000..8076aa921 --- /dev/null +++ b/src/abd/test_abd_issue.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f` + +# (1) PKEY1.user -> PKEY2.resu.user +# (2) PKEY2.resu -> PKEY3 +# (3) PKEY3.user -> PKEY4 + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30" + +TEST_ATTR="test" +gnunet-arm -s -c test_abd_lookup.conf +gnunet-identity -C testissuer -c test_abd_lookup.conf +gnunet-identity -C testsubject -c test_abd_lookup.conf +SUBJECT_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep testsubject | awk '{print $3}') +ISSUER_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep testissuer | awk '{print $3}') + +# Get abd and store it with subject (3) +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=testissuer --attribute=$TEST_ATTR --subject=$SUBJECT_KEY --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf` + +STATUS=$? + +if test $? != 0 +then + echo "Error issuing..." + exit 1 +fi +#Try import +$DO_TIMEOUT gnunet-abd --createSubjectSide --ego=testsubject --import="$SIGNED" --private -c test_abd_lookup.conf +RES=$? +gnunet-arm -e -c test_abd_lookup.conf +exit $RES diff --git a/src/abd/test_abd_lookup.conf b/src/abd/test_abd_lookup.conf new file mode 100644 index 000000000..4072ba23b --- /dev/null +++ b/src/abd/test_abd_lookup.conf @@ -0,0 +1,28 @@ +@INLINE@ test_abd_defaults.conf + +[PATHS] +GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-abd-peer-1/ + +[dht] +START_ON_DEMAND = YES + +[transport] +PLUGINS = + +[abd] +START_ON_DEMAND = YES +#PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/credlog + +[rest] +PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=$GNUNET_TMP/restlog + +[gns] +#PREFIX = valgrind --leak-check=full --track-origins=yes +START_ON_DEMAND = YES +AUTO_IMPORT_PKEY = YES +MAX_PARALLEL_BACKGROUND_QUERIES = 10 +DEFAULT_LOOKUP_TIMEOUT = 15 s +RECORD_PUT_INTERVAL = 1 h +ZONE_PUBLISH_TIME_WINDOW = 1 h +DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0 + diff --git a/src/abd/test_abd_own.sh b/src/abd/test_abd_own.sh new file mode 100755 index 000000000..f4780ea90 --- /dev/null +++ b/src/abd/test_abd_own.sh @@ -0,0 +1,140 @@ +#!/usr/bin/env bash +trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f` + + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10" +gnunet-arm -s -c test_abd_lookup.conf + +gnunet-identity -C a -c test_abd_lookup.conf +gnunet-identity -C d -c test_abd_lookup.conf +gnunet-identity -C e -c test_abd_lookup.conf +gnunet-identity -C f -c test_abd_lookup.conf +gnunet-identity -C g -c test_abd_lookup.conf +AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}') +DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}') +EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}') +FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}') +GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}') + +############################################################################################ +# (1) EPub.discount <- EOrg.preferred +# (2) EOrg.preferred <- StateU.student +# (3) StateU.student <- RegistrarB.student +# (4) RegistrarB.student <- Alice + +gnunet-identity -C epub -c test_abd_lookup.conf +gnunet-identity -C eorg -c test_abd_lookup.conf +gnunet-identity -C stateu -c test_abd_lookup.conf +gnunet-identity -C registrarb -c test_abd_lookup.conf +gnunet-identity -C alice -c test_abd_lookup.conf + +EPUB_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep epub | awk '{print $3}') +EORG_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep eorg | awk '{print $3}') +STATEU_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep stateu | awk '{print $3}') +REGISTRARB_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep registrarb | awk '{print $3}') +ALICE_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep alice | awk '{print $3}') + + +DISC_ATTR="discount" +PREF_ATTR="preferred" +STATE_STUD_ATTR="student" +REG_STUD_ATTR="student" +END_ATTR="end" + +gnunet-identity -d + +# FORWARD, subject side stored (different constallations) +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=a --attribute="a" --subject="$AKEY b.c" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=a --import="$SIGNED" +gnunet-namestore -D -z a + +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=a --attribute="b" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=d --import="$SIGNED" +gnunet-namestore -D -z d + +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=e --import="$SIGNED" +gnunet-namestore -D -z e + +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="c" --subject="$FKEY c" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="k" --subject="$FKEY c.k" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" +gnunet-namestore -D -z f + +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=f --attribute="c" --subject="$GKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=g --import="$SIGNED" --private +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=a --attribute="c" --subject="$GKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=g --import="$SIGNED" --private +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="h.o" --subject="$GKEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=g --import="$SIGNED" +gnunet-namestore -D -z g + + +# BACKWARD, issuer side stored +# (1) EPub assigns the attribute "discount" to all entities that have been assigned "preferred" by EOrg +gnunet-abd --createIssuerSide --ego=epub --attribute=$DISC_ATTR --subject="$EORG_KEY $PREF_ATTR" --ttl=5m -c test_abd_lookup.conf + +# (2) EOrg assigns the attribute "preferred" to all entities that have been assigned "student" by StateU +gnunet-abd --createIssuerSide --ego=eorg --attribute=$PREF_ATTR --subject="$STATEU_KEY $STATE_STUD_ATTR" --ttl=5m -c test_abd_lookup.conf + +# (3) StateU assigns the attribute "student" to all entities that have been asssigned "student" by RegistrarB +gnunet-abd --createIssuerSide --ego=stateu --attribute=$STATE_STUD_ATTR --subject="$REGISTRARB_KEY $REG_STUD_ATTR" --ttl=5m -c test_abd_lookup.conf + +# (4) RegistrarB issues Alice the credential "student" +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=registrarb --attribute="$REG_STUD_ATTR" --subject="$ALICE_KEY" --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=alice --import="$SIGNED" --private + +# Starting to resolve +echo "+++ Starting to Resolve +++" + +# FORWARD +#DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=g --forward -c test_abd_lookup.conf | paste -d, -s - -` +#echo $DELS +#echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$GKEY --delegate=\'$DELS\' --forward -c test_abd_lookup.conf +#RES_DELS=`gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$GKEY --delegate="$DELS" --forward -c test_abd_lookup.conf` + +# BACKWARD +DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$EPUB_KEY --attribute=$DISC_ATTR --ego=alice --backward -c test_abd_lookup.conf | paste -d, -s - -` +echo $DELS +echo gnunet-abd --verify --issuer=$EPUB_KEY --attribute=$DISC_ATTR --subject=$ALICE_KEY --delegate=\'$DELS\' --backward -c test_abd_lookup.conf +gnunet-abd --verify --issuer=$EPUB_KEY --attribute=$DISC_ATTR --subject=$ALICE_KEY --delegate="$DELS" --backward -c test_abd_lookup.conf + +RES=$? + +# Cleanup properly +gnunet-namestore -z epub -d -n $DISC_ATTR -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z eorg -d -n $PREF_ATTR -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z stateu -d -n $STATE_STUD_ATTR -t ATTR -c test_abd_lookup.conf +#gnunet-namestore -z a -d -n "@" -t DEL -c test_abd_lookup.conf +#gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf +#gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf +#gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf +#gnunet-namestore -z g -d -n "@" -t DEL -c test_abd_lookup.conf + + +gnunet-arm -e -c test_abd_lookup.conf + +if [ "$RES" == 0 ] +then + exit 0 +else + echo "FAIL: Failed to verify credential." + exit 1 +fi + diff --git a/src/abd/test_abd_verify.sh b/src/abd/test_abd_verify.sh new file mode 100755 index 000000000..9ece91c62 --- /dev/null +++ b/src/abd/test_abd_verify.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f` + +# (1) Service.user -> GNU.project.member +# (2) GNU.project -> GNUnet +# (3) GNUnet.member -> GNUnet.developer +# (4) GNUnet.member -> GNUnet.user +# (5) GNUnet.developer -> Alice + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30" +gnunet-arm -s -c test_abd_lookup.conf +gnunet-identity -C service -c test_abd_lookup.conf +gnunet-identity -C alice -c test_abd_lookup.conf +gnunet-identity -C gnu -c test_abd_lookup.conf +gnunet-identity -C gnunet -c test_abd_lookup.conf + +GNU_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}') +ALICE_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep alice | awk '{print $3}') +GNUNET_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep gnunet | awk '{print $3}') +SERVICE_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep service | awk '{print $3}') + +USER_ATTR="user" +GNU_PROJECT_ATTR="project" +MEMBER_ATTR="member" +DEVELOPER_ATTR="developer" +DEV_ATTR="developer" +TEST_CREDENTIAL="mygnunetcreds" + +gnunet-identity -d + +# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU +gnunet-abd --createIssuerSide --ego=service --attribute="$USER_ATTR" --subject="$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf +gnunet-namestore -D -z service + +# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute +gnunet-abd --createIssuerSide --ego=gnu --attribute="$GNU_PROJECT_ATTR" --subject="$GNUNET_KEY" --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf +gnunet-namestore -D -z gnu + +# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user" +gnunet-abd --createIssuerSide --ego=gnunet --attribute="$MEMBER_ATTR" --subject="$GNUNET_KEY $DEVELOPER_ATTR" --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf +gnunet-abd --createIssuerSide --ego=gnunet --attribute="$MEMBER_ATTR" --subject="$GNUNET_KEY $USER_ATTR" --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf +gnunet-namestore -D -z gnunet + +# (5) GNUnet signes the delegate and Alice stores it +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=gnunet --attribute=$DEV_ATTR --subject=$ALICE_KEY --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=alice --import="$SIGNED" --private +gnunet-namestore -D -z alice + +# Starting to resolve +echo "+++ Starting to Resolve +++" + +DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice --backward -c test_abd_lookup.conf | paste -d, -s - -` +echo $DELS +echo gnunet-abd --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --delegate=\'$DELS\' --backward -c test_abd_lookup.conf +gnunet-abd --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --delegate="$DELS" --backward -c test_abd_lookup.conf + +RES=$? + +# Cleanup properly +gnunet-namestore -z alice -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_abd_lookup.conf +gnunet-arm -e -c test_abd_lookup.conf + +if [ "$RES" == 0 ] +then + exit 0 +else + echo "FAIL: Failed to verify credential." + exit 1 +fi diff --git a/src/abd/test_abd_verify_and.sh b/src/abd/test_abd_verify_and.sh new file mode 100755 index 000000000..c6287055e --- /dev/null +++ b/src/abd/test_abd_verify_and.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env bash +trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f` + +# (1) Service.user -> GNU.project.member +# (2) GNU.project -> GNUnet +# (3) GNUnet.member -> GNUnet.developer AND GNUnet.user +# (4) GNUnet.developer -> Alice + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30" +gnunet-arm -s -c test_abd_lookup.conf +gnunet-identity -C service -c test_abd_lookup.conf +gnunet-identity -C alice -c test_abd_lookup.conf +gnunet-identity -C gnu -c test_abd_lookup.conf +gnunet-identity -C gnunet -c test_abd_lookup.conf + +GNU_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}') +ALICE_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep alice | awk '{print $3}') +GNUNET_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep gnunet | awk '{print $3}') +SERVICE_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep service | awk '{print $3}') + +USER_ATTR="user" +GNU_PROJECT_ATTR="project" +MEMBER_ATTR="member" +DEVELOPER_ATTR="developer" +DEV_ATTR="developer" + +gnunet-identity -d + +# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU +gnunet-abd --createIssuerSide --ego=service --attribute="$USER_ATTR" --subject="$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf +gnunet-namestore -D -z service + +# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute +gnunet-abd --createIssuerSide --ego=gnu --attribute="$GNU_PROJECT_ATTR" --subject="$GNUNET_KEY" --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf +gnunet-namestore -D -z gnu + +# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user" +gnunet-abd --createIssuerSide --ego=gnunet --attribute="$MEMBER_ATTR" --subject="$GNUNET_KEY $DEVELOPER_ATTR, $GNUNET_KEY $USER_ATTR" --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf +gnunet-namestore -D -z gnunet + +# (5) GNUnet signes the delegates and Alice stores it +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=gnunet --attribute=$DEV_ATTR --subject=$ALICE_KEY --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=alice --import="$SIGNED" --private +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=gnunet --attribute=$USER_ATTR --subject=$ALICE_KEY --ttl="2019-12-12 10:00:00"` +gnunet-abd --createSubjectSide --ego=alice --import="$SIGNED" --private +gnunet-namestore -D -z alice + +# Starting to resolve +echo "+++ Starting to Resolve +++" + +DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice --backward -c test_abd_lookup.conf | paste -d, -s - -` +echo $DELS +echo gnunet-abd --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --delegate=\'$DELS\' --backward -c test_abd_lookup.conf +gnunet-abd --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --delegate="$DELS" --backward -c test_abd_lookup.conf + +RES=$? + +# Cleanup properly +gnunet-namestore -z alice -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_abd_lookup.conf +gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_abd_lookup.conf +gnunet-arm -e -c test_abd_lookup.conf + +if [ "$RES" == 0 ] +then + exit 0 +else + echo "FAIL: Failed to verify credentials." + exit 1 +fi diff --git a/src/abd/test_abd_verify_simple.sh b/src/abd/test_abd_verify_simple.sh new file mode 100755 index 000000000..e917f8793 --- /dev/null +++ b/src/abd/test_abd_verify_simple.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f` + +# (1) Issuer.user -> Subject + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30" +gnunet-arm -s -c test_abd_lookup.conf +gnunet-identity -C testissuer -c test_abd_lookup.conf +gnunet-identity -C testsubject -c test_abd_lookup.conf + +TEST_ATTR="user" +SUBJECT_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep testsubject | awk '{print $3}') +ISSUER_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep testissuer | awk '{print $3}') + +gnunet-identity -d + +# Create delegate (1) +SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=testissuer --attribute=$TEST_ATTR --subject=$SUBJECT_KEY --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf` +gnunet-abd --createSubjectSide --ego=testsubject --import="$SIGNED" --private +gnunet-namestore -D -z testsubject + +# Starting to resolve +echo "+++ Starting to Resolve +++" + +DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --ego=testsubject -c test_abd_lookup.conf | paste -d, -s - -` +echo $DELS +gnunet-abd --verify --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --subject=$SUBJECT_KEY --delegate="$DELS" -c test_abd_lookup.conf + +RES=$? + +# Cleanup properly +gnunet-namestore -z testsubject -d -n "@" -t DEL -c test_abd_lookup.conf +gnunet-arm -e -c test_abd_lookup.conf + +if [ "$RES" == 0 ] +then + exit 0 +else + echo "FAIL: Failed to verify credential." + exit 1 +fi \ No newline at end of file diff --git a/src/abd/test_credential_collect.sh b/src/abd/test_credential_collect.sh new file mode 100755 index 000000000..0ae063eda --- /dev/null +++ b/src/abd/test_credential_collect.sh @@ -0,0 +1,47 @@ +#!/bin/sh +trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f` + +# (1) PKEY1.user -> PKEY2.resu.user +# (2) PKEY2.resu -> PKEY3 +# (3) PKEY3.user -> PKEY4 + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30" + +TEST_ATTR="test" +TEST_ATTR2="test2" +gnunet-arm -s -c test_credential_lookup.conf +gnunet-identity -C testissuer -c test_credential_lookup.conf +gnunet-identity -C testsubject -c test_credential_lookup.conf +SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}') +ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}') +#TODO1 Get credential and store it with subject (3) +CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf` +$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf +CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR2 --ttl=5m -c test_credential_lookup.conf` +$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c2 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf +CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --ego=testsubject -c test_credential_lookup.conf | paste -d, -s` +echo $CREDS +RES=$? +gnunet-arm -e -c test_credential_lookup.conf + +if test $? != 0 +then + echo "Error collecting..." + exit 1 +fi + diff --git a/src/abd/test_credential_collect_rest.sh b/src/abd/test_credential_collect_rest.sh new file mode 100755 index 000000000..fe59d9399 --- /dev/null +++ b/src/abd/test_credential_collect_rest.sh @@ -0,0 +1,91 @@ +#!/bin/sh +trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f` + +# (1) Service.user -> GNU.project.member +# (2) GNU.project -> GNUnet +# (3) GNUnet.member -> GNUnet.developer +# (4) GNUnet.member -> GNUnet.user +# (5) GNUnet.developer -> Alice + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30" +gnunet-arm -s -c test_credential_lookup.conf +gnunet-identity -C service -c test_credential_lookup.conf +gnunet-identity -C alice -c test_credential_lookup.conf +gnunet-identity -C gnu -c test_credential_lookup.conf +gnunet-identity -C gnunet -c test_credential_lookup.conf + +GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}') +ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}') +GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}') +SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}') + +USER_ATTR="user" +GNU_PROJECT_ATTR="project" +MEMBER_ATTR="member" +DEVELOPER_ATTR="developer" +DEV_ATTR="developer" +TEST_CREDENTIAL="mygnunetcreds" + +# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU +gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf + +# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute +gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf + +# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user" +gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf +gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf + +# (5) GNUnet issues Alice the credential "developer" +CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf` + +# Alice stores the credential under "mygnunetcreds" +gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf + +# (5) GNUnet issues Alice the credential "developer" +CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$USER_ATTR --ttl=5m -c test_credential_lookup.conf` + +# Alice stores the credential under "mygnunetcreds" +gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf + +#TODO2 Add -z swich like in gnunet-gns +#RES_CRED=`gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY -c test_credential_lookup.conf` + +gnunet-arm -i rest -c test_credential_lookup.conf + +sleep 5 + +curl -v "localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice" + +#TODO cleanup properly +gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf +gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf +gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf +gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf +echo "Stopping arm..." +gnunet-arm -e -c test_credential_lookup.conf +echo "Done" +if [ "$RES_CRED" != "Failed." ] +then + # TODO: replace echo -e bashism. + echo -e "${RES_CRED}" + exit 0 +else + echo "FAIL: Failed to verify credential $RES_CRED." + exit 1 +fi diff --git a/src/abd/test_credential_issue_rest.sh b/src/abd/test_credential_issue_rest.sh new file mode 100755 index 000000000..c518c08ec --- /dev/null +++ b/src/abd/test_credential_issue_rest.sh @@ -0,0 +1,53 @@ +#!/bin/sh +trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f` + +# (1) PKEY1.user -> PKEY2.resu.user +# (2) PKEY2.resu -> PKEY3 +# (3) PKEY3.user -> PKEY4 + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30" + +TEST_ATTR="test" +gnunet-arm -s -c test_credential_lookup.conf +gnunet-arm -i gns +gnunet-arm -i credential +gnunet-arm -i identity +gnunet-arm -i rest -c test_credential_lookup.conf + +gnunet-arm -I -c test_credential_lookup.conf +gnunet-identity -C testissuer -c test_credential_lookup.conf +gnunet-identity -C testsubject -c test_credential_lookup.conf +gnunet-identity -s credential-issuer -e testissuer +SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}') +ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}') +#TODO1 Get credential and store it with subject (3) +sleep 5 +curl "localhost:7776/credential/issue?subject_key=$SUBJECT_KEY&attribute=$TEST_ATTR&expiration=1d" +#CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf` +STATUS=$? + +if test $? != 0 +then + echo "Error issuing..." + exit 1 +fi +#Try import +#$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf +RES=$? +gnunet-arm -e -c test_credential_lookup.conf +exit $RES diff --git a/src/abd/test_credential_verify_rest.sh b/src/abd/test_credential_verify_rest.sh new file mode 100755 index 000000000..99db5da8a --- /dev/null +++ b/src/abd/test_credential_verify_rest.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1> /dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f` + +# (1) Service.user -> GNU.project.member +# (2) GNU.project -> GNUnet +# (3) GNUnet.member -> GNUnet.developer +# (4) GNUnet.member -> GNUnet.user +# (5) GNUnet.developer -> Alice + + +which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30" +gnunet-arm -s -c test_credential_lookup.conf +gnunet-identity -C service -c test_credential_lookup.conf +gnunet-identity -C alice -c test_credential_lookup.conf +gnunet-identity -C gnu -c test_credential_lookup.conf +gnunet-identity -C gnunet -c test_credential_lookup.conf + +GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}') +ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}') +GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}') +SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}') + +USER_ATTR="user" +GNU_PROJECT_ATTR="project" +MEMBER_ATTR="member" +DEVELOPER_ATTR="developer" +DEV_ATTR="developer" +TEST_CREDENTIAL="mygnunetcreds" + +# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU +gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf + +# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute +gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf + +# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user" +gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf +gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf + +# (5) GNUnet issues Alice the credential "developer" +CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf` + +# Alice stores the credential under "mygnunetcreds" +gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf + +#TODO2 Add -z swich like in gnunet-gns +#RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf` + +gnunet-arm -i rest -c test_credential_lookup.conf + +sleep 5 + +CREDS=`curl "localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice"` + +echo $CREDS + +curl -v "localhost:7776/credential/verify?attribute=$SERVICE_KEY.$USER_ATTR&subject_key=$ALICE_KEY" --data "$CREDS" + +#TODO cleanup properly +gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf +gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf +gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf +gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf +gnunet-arm -e -c test_credential_lookup.conf + +if [ "$RES_CRED" != "Failed." ] +then + # TODO: replace echo -e bashism + echo -e "${RES_CRED}" + exit 0 +else + echo "FAIL: Failed to verify credential $RES_CRED." + exit 1 +fi -- cgit v1.2.3