src/hello/Makefile
src/identity/Makefile
src/identity/identity.conf
+src/credential/Makefile
+src/credential/credential.conf
src/include/Makefile
src/integration-tests/Makefile
src/json/Makefile
src/core/gnunet-service-core_kx.c
src/core/gnunet-service-core_sessions.c
src/core/gnunet-service-core_typemap.c
+src/credential/credential_api.c
+src/credential/gnunet-credential.c
+src/credential/gnunet-service-credential.c
+src/credential/plugin_gnsrecord_credential.c
src/curl/curl.c
src/curl/curl_reschedule.c
src/datacache/datacache.c
revocation \
vpn \
gns \
+ credential \
zonemaster \
$(CONVERSATION_DIR) \
fs \
--- /dev/null
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+EXTRA_DIST = \
+ test_credential_defaults.conf \
+ test_credential_lookup.conf
+
+
+if USE_COVERAGE
+ AM_CFLAGS = --coverage -O0
+endif
+
+pkgcfgdir = $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+plugindir = $(libdir)/gnunet
+
+pkgcfg_DATA = \
+ credential.conf
+
+
+# /usr/lib - compiles a layer which can be used to be communicagte with the service
+lib_LTLIBRARIES = \
+ libgnunetcredential.la
+
+# /usr/lib/gnunet/libexec - Business logic . Separate process
+libexec_PROGRAMS = \
+ gnunet-service-credential
+
+bin_PROGRAMS = \
+ gnunet-credential
+
+plugin_LTLIBRARIES = \
+ libgnunet_plugin_gnsrecord_credential.la
+
+
+if HAVE_MHD
+if HAVE_JSON
+plugin_LTLIBRARIES += libgnunet_plugin_rest_credential.la
+endif
+endif
+
+
+gnunet_credential_SOURCES = \
+ gnunet-credential.c
+gnunet_credential_LDADD = \
+ libgnunetcredential.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
+ $(top_builddir)/src/identity/libgnunetidentity.la \
+ $(GN_LIBINTL)
+
+
+libgnunet_plugin_gnsrecord_credential_la_SOURCES = \
+ plugin_gnsrecord_credential.c
+libgnunet_plugin_gnsrecord_credential_la_LIBADD = \
+ libgnunetcredential.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(LTLIBINTL)
+libgnunet_plugin_gnsrecord_credential_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
+
+gnunet_service_credential_SOURCES = \
+ gnunet-service-credential.c
+gnunet_service_credential_LDADD = \
+ libgnunetcredential.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)
+
+
+libgnunetcredential_la_SOURCES = \
+ credential_api.c \
+ credential_serialization.c \
+ credential_misc.c
+libgnunetcredential_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
+libgnunetcredential_la_LDFLAGS = \
+ $(GN_LIB_LDFLAGS)
+
+
+libgnunet_plugin_rest_credential_la_SOURCES = \
+ plugin_rest_credential.c
+libgnunet_plugin_rest_credential_la_LIBADD = \
+ libgnunetcredential.la \
+ $(top_builddir)/src/rest/libgnunetrest.la \
+ $(top_builddir)/src/identity/libgnunetidentity.la \
+ $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
+ $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \
+ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+ $(LTLIBINTL) -ljansson -lmicrohttpd
+libgnunet_plugin_rest_credential_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
+check_SCRIPTS = \
+ test_credential_issue.sh \
+ test_credential_verify_simple.sh \
+ test_credential_verify.sh \
+ test_credential_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
--- /dev/null
+[credential]
+BINARY = gnunet-service-credential
+UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-credential.sock
+USER_SERVICE = YES
+OPTIONS = -L DEBUG
\ No newline at end of file
--- /dev/null
+/*
+ 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 General Public License as published
+ by the Free Software Foundation; either version 3, 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+/**
+ * @file credential/credential.h
+ * @brief IPC messages between CREDENTIAL API and CREDENTIAL service
+ * @author Adnan Husain
+ */
+#ifndef CREDENTIAL_H
+#define CREDENTIAL_H
+
+#include "gnunet_credential_service.h"
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Message from client to Credential service to collect credentials.
+ */
+struct CollectMessage
+{
+ /**
+ * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_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;
+
+ /**
+ * 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_CREDENTIAL_VERIFY
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Subject public key
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * Trust anchor
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * Number of credentials
+ */
+ uint32_t c_count;
+
+ /**
+ * Length of the issuer attribute
+ */
+ uint16_t issuer_attribute_len;
+
+ /**
+ * 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 CREDENTIAL service to client: new results.
+ */
+struct DelegationChainResultMessage
+{
+ /**
+ * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_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 cred_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_CREDENTIAL_RecordData structs*/
+
+};
+
+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
+ */
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
+
--- /dev/null
+/*
+ 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 General Public License as published
+ by the Free Software Foundation; either version 3, 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file credential/credential_api.c
+ * @brief library to access the CREDENTIAL service
+ * @author Adnan Husain
+ */
+#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 "credential.h"
+#include "credential_serialization.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_identity_service.h"
+
+
+#define LOG(kind,...) GNUNET_log_from (kind, "credential-api",__VA_ARGS__)
+
+/**
+ * Handle to a verify request
+ */
+struct GNUNET_CREDENTIAL_Request
+{
+
+ /**
+ * DLL
+ */
+ struct GNUNET_CREDENTIAL_Request *next;
+
+ /**
+ * DLL
+ */
+ struct GNUNET_CREDENTIAL_Request *prev;
+
+ /**
+ * handle to credential service
+ */
+ struct GNUNET_CREDENTIAL_Handle *credential_handle;
+
+ /**
+ * processor to call on verify result
+ */
+ GNUNET_CREDENTIAL_CredentialResultProcessor verify_proc;
+
+ /**
+ * @e verify_proc closure
+ */
+ void *proc_cls;
+
+ /**
+ * Envelope with the message for this queue entry.
+ */
+ struct GNUNET_MQ_Envelope *env;
+
+ /**
+ * request id
+ */
+ uint32_t r_id;
+
+};
+
+
+/**
+ * Connection to the CREDENTIAL service.
+ */
+struct GNUNET_CREDENTIAL_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_CREDENTIAL_Request *request_head;
+
+ /**
+ * Tail of linked list of active verify requests.
+ */
+ struct GNUNET_CREDENTIAL_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 CREDENTIAL service.
+ *
+ * @param handle the handle to the CREDENTIAL service
+ */
+static void
+reconnect (struct GNUNET_CREDENTIAL_Handle *handle);
+
+
+/**
+ * Reconnect to CREDENTIAL
+ *
+ * @param cls the handle
+ */
+static void
+reconnect_task (void *cls)
+{
+ struct GNUNET_CREDENTIAL_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_CREDENTIAL_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_CREDENTIAL_Handle *`
+ * @param error error code
+ */
+static void
+mq_error_handler (void *cls,
+ enum GNUNET_MQ_Error error)
+{
+ struct GNUNET_CREDENTIAL_Handle *handle = cls;
+
+ force_reconnect (handle);
+}
+
+/**
+ * Check validity of message received from the CREDENTIAL service
+ *
+ * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
+ * @param loookup_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 CREDENTIAL service
+ *
+ * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
+ * @param loookup_msg the incoming message
+ */
+static void
+handle_result (void *cls,
+ const struct DelegationChainResultMessage *vr_msg)
+{
+ struct GNUNET_CREDENTIAL_Handle *handle = cls;
+ uint32_t r_id = ntohl (vr_msg->id);
+ struct GNUNET_CREDENTIAL_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_CREDENTIAL_Delegation d_chain[d_count];
+ struct GNUNET_CREDENTIAL_Credential creds[c_count];
+ GNUNET_CREDENTIAL_CredentialResultProcessor proc;
+ void *proc_cls;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Received verify reply from CREDENTIAL 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_CREDENTIAL_delegation_chain_deserialize (mlen,
+ (const char*) &vr_msg[1],
+ d_count,
+ d_chain,
+ c_count,
+ creds));
+ if (GNUNET_NO == ntohl (vr_msg->cred_found))
+ {
+ proc (proc_cls,
+ 0,
+ NULL,
+ 0,
+ NULL); // TODO
+ } else {
+ proc (proc_cls,
+ d_count,
+ d_chain,
+ c_count,
+ creds);
+ }
+}
+
+
+/**
+ * Reconnect to CREDENTIAL service.
+ *
+ * @param handle the handle to the CREDENTIAL service
+ */
+static void
+reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
+{
+ struct GNUNET_MQ_MessageHandler handlers[] = {
+ GNUNET_MQ_hd_var_size (result,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT,
+ struct DelegationChainResultMessage,
+ handle),
+ GNUNET_MQ_hd_var_size (result,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT,
+ struct DelegationChainResultMessage,
+ handle),
+ GNUNET_MQ_handler_end ()
+ };
+ struct GNUNET_CREDENTIAL_Request *vr;
+
+ GNUNET_assert (NULL == handle->mq);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to connect to CREDENTIAL\n");
+ handle->mq = GNUNET_CLIENT_connect (handle->cfg,
+ "credential",
+ 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 CREDENTIAL service.
+ *
+ * @param cfg configuration to use
+ * @return handle to the CREDENTIAL service, or NULL on error
+ */
+struct GNUNET_CREDENTIAL_Handle *
+GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ struct GNUNET_CREDENTIAL_Handle *handle;
+
+ handle = GNUNET_new (struct GNUNET_CREDENTIAL_Handle);
+ handle->cfg = cfg;
+ reconnect (handle);
+ if (NULL == handle->mq)
+ {
+ GNUNET_free (handle);
+ return NULL;
+ }
+ return handle;
+}
+
+
+/**
+ * Shutdown connection with the CREDENTIAL service.
+ *
+ * @param handle handle of the CREDENTIAL connection to stop
+ */
+void
+GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_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_CREDENTIAL_request_cancel (struct GNUNET_CREDENTIAL_Request *vr)
+{
+ struct GNUNET_CREDENTIAL_Handle *handle = vr->credential_handle;
+
+ GNUNET_CONTAINER_DLL_remove (handle->request_head,
+ handle->request_tail,
+ vr);
+ GNUNET_MQ_discard (vr->env);
+ GNUNET_free (vr);
+}
+
+
+/**
+ * Performs attribute collection.
+ * Collects all credentials 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 credential_count number of credentials provided
+ * @param credentials subject credentials
+ * @param proc function to call on result
+ * @param proc_cls closure for processor
+ * @return handle to the queued request
+ */
+struct GNUNET_CREDENTIAL_Request*
+GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
+ const char *issuer_attribute,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key,
+ GNUNET_CREDENTIAL_CredentialResultProcessor proc,
+ void *proc_cls)
+{
+ /* IPC to shorten credential names, return shorten_handle */
+ struct CollectMessage *c_msg;
+ struct GNUNET_CREDENTIAL_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 CREDENTIAL\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_CREDENTIAL_Request);
+ vr->credential_handle = handle;
+ vr->verify_proc = proc;
+ vr->proc_cls = proc_cls;
+ vr->r_id = handle->r_id_gen++;
+ vr->env = GNUNET_MQ_msg_extra (c_msg,
+ nlen,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_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));
+ 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 credential_count number of credentials provided
+ * @param credentials subject credentials
+ * @param proc function to call on result
+ * @param proc_cls closure for processor
+ * @return handle to the queued request
+ */
+struct GNUNET_CREDENTIAL_Request*
+GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
+ const char *issuer_attribute,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
+ uint32_t credential_count,
+ const struct GNUNET_CREDENTIAL_Credential *credentials,
+ GNUNET_CREDENTIAL_CredentialResultProcessor proc,
+ void *proc_cls)
+{
+ /* IPC to shorten credential names, return shorten_handle */
+ struct VerifyMessage *v_msg;
+ struct GNUNET_CREDENTIAL_Request *vr;
+ size_t nlen;
+ size_t clen;
+
+ if (NULL == issuer_attribute || NULL == credentials)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+
+ clen = GNUNET_CREDENTIAL_credentials_get_size (credential_count,
+ credentials);
+
+ //DEBUG LOG
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to verify `%s' in CREDENTIAL\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_CREDENTIAL_Request);
+ vr->credential_handle = handle;
+ vr->verify_proc = proc;
+ vr->proc_cls = proc_cls;
+ vr->r_id = handle->r_id_gen++;
+ vr->env = GNUNET_MQ_msg_extra (v_msg,
+ nlen,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY);
+ v_msg->id = htonl (vr->r_id);
+ v_msg->subject_key = *subject_key;
+ v_msg->c_count = htonl(credential_count);
+ v_msg->issuer_key = *issuer_key;
+ v_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
+ GNUNET_memcpy (&v_msg[1],
+ issuer_attribute,
+ strlen (issuer_attribute));
+ GNUNET_CREDENTIAL_credentials_serialize (credential_count,
+ credentials,
+ 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 credential_api.c */
--- /dev/null
+/*
+ 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 General Public License as published
+ by the Free Software Foundation; either version 3, 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+/**
+ * @file credential/credential_mic.c
+ * @brief Misc API for credentials
+ *
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_signatures.h"
+#include "credential.h"
+#include <inttypes.h>
+
+char*
+GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *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);
+ GNUNET_asprintf (&cred_str,
+ "%s.%s -> %s | %s | %"SCNu64,
+ issuer_pkey,
+ cred->issuer_attribute,
+ subject_pkey,
+ signature,
+ cred->expiration.abs_value_us);
+ GNUNET_free (subject_pkey);
+ GNUNET_free (issuer_pkey);
+ GNUNET_free (signature);
+ return cred_str;
+}
+
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_from_string (const char* s)
+{
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ 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 name[253 + 1];
+ char signature[256]; //TODO max payload size
+
+ struct GNUNET_CRYPTO_EcdsaSignature *sig;
+ struct GNUNET_TIME_Absolute etime_abs;
+
+ if (5 != SSCANF (s,
+ "%52s.%253s -> %52s | %s | %"SCNu64,
+ issuer_pkey,
+ name,
+ subject_pkey,
+ signature,
+ &etime_abs.abs_value_us))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Unable to parse CRED record string `%s'\n"),
+ s);
+ return NULL;
+ }
+ cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (name) + 1);
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
+ strlen (subject_pkey),
+ &cred->subject_key);
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_pkey,
+ strlen (issuer_pkey),
+ &cred->issuer_key);
+ GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdsaSignature) == GNUNET_STRINGS_base64_decode (signature,
+ strlen (signature),
+ (char**)&sig));
+ cred->signature = *sig;
+ cred->expiration = etime_abs;
+ GNUNET_free (sig);
+ GNUNET_memcpy (&cred[1],
+ name,
+ strlen (name)+1);
+ cred->issuer_attribute_len = strlen ((char*)&cred[1]);
+ cred->issuer_attribute = (char*)&cred[1];
+ return cred;
+}
+
+/**
+ * Issue an attribute to a subject
+ *
+ * @param handle handle to the Credential service
+ * @param issuer the ego that should be used to issue the attribute
+ * @param subject the subject of the attribute
+ * @param attribute the name of the attribute
+ * @return handle to the queued request
+ */
+struct GNUNET_CREDENTIAL_Credential *
+GNUNET_CREDENTIAL_credential_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
+ struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
+ const char *attribute,
+ struct GNUNET_TIME_Absolute *expiration)
+{
+ struct CredentialEntry *crd;
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ size_t size;
+
+ size = sizeof (struct CredentialEntry) + strlen (attribute) + 1;
+ crd = GNUNET_malloc (size);
+ cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (attribute) + 1);
+ crd->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+
+ crd->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
+ GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
+ &crd->issuer_key);
+ crd->subject_key = *subject;
+ crd->expiration = GNUNET_htonll (expiration->abs_value_us);
+ crd->issuer_attribute_len = htonl (strlen (attribute)+1);
+ GNUNET_memcpy ((char*)&crd[1],
+ attribute,
+ strlen (attribute)+1);
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_ecdsa_sign (issuer,
+ &crd->purpose,
+ &crd->signature))
+ {
+ GNUNET_break (0);
+ GNUNET_free (crd);
+ return NULL;
+ }
+ cred->signature = crd->signature;
+ cred->expiration = *expiration;
+ GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
+ &cred->issuer_key);
+
+ cred->subject_key = *subject;
+ GNUNET_memcpy (&cred[1],
+ attribute,
+ strlen (attribute)+1);
+ cred->issuer_attribute = (char*)&cred[1];
+ GNUNET_free (crd);
+ return cred;
+}
+
+
--- /dev/null
+/*
+ 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 General Public License as published
+ by the Free Software Foundation; either version 3, 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+/**
+ * @file credential/credential_misc.h
+ * @brief Credential helper functions
+ */
+#ifndef CREDENTIAL_MISC_H
+#define CREDENTIAL_MISC_H
+
+
+
+char*
+GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *cred);
+
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_from_string (const char* str);
+
+#endif
--- /dev/null
+/*
+ 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 General Public License as published
+ by the Free Software Foundation; either version 3, 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+/**
+ * @file credential/credential_serialization.c
+ * @brief API to serialize and deserialize delegation chains
+ * and credentials
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_signatures.h"
+#include "credential.h"
+
+/**
+ * Calculate how many bytes we will need to serialize
+ * the given delegation chain and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
+ const struct GNUNET_CREDENTIAL_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 credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param cd a #GNUNET_CREDENTIAL_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_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
+ const struct GNUNET_CREDENTIAL_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 dd where to put the delegation chain entries
+ * @param cd where to put the credential data
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
+ const char *src,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_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 credentials
+ *
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *cd)
+{
+ unsigned int i;
+ size_t ret;
+
+ ret = sizeof (struct CredentialEntry) * (c_count);
+
+ for (i=0; i<c_count;i++)
+ {
+ GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
+ ret += cd[i].issuer_attribute_len;
+ }
+ return ret;
+}
+/**
+ * Serizalize the given credentials
+ *
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_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_CREDENTIAL_credentials_serialize (unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *cd,
+ size_t dest_size,
+ char *dest)
+{
+ struct CredentialEntry c_rec;
+ unsigned int i;
+ size_t off;
+
+ off = 0;
+ for (i=0;i<c_count;i++)
+ {
+ 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_CREDENTIAL);
+ c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + 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 credential entries
+ * @param cd where to put the credential data
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
+ const char *src,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cd)
+{
+ struct CredentialEntry 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;
+ }
+ return GNUNET_OK;
+}
+
+
+
+/**
+ * Calculate how many bytes we will need to serialize
+ * the given delegation chain and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
+ const struct GNUNET_CREDENTIAL_Delegation *dd,
+ unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *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_CREDENTIAL_credentials_get_size(c_count, cd);
+ return ret;
+}
+
+/**
+ * Serizalize the given delegation chain entries and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_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_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
+ const struct GNUNET_CREDENTIAL_Delegation *dd,
+ unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *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_CREDENTIAL_credentials_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 credential entries
+ * @param cd where to put the credential data
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
+ const char *src,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_Delegation *dd,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *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_CREDENTIAL_credentials_deserialize (len-off,
+ &src[off],
+ c_count,
+ cd);
+}
+int
+GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
+ char **data)
+{
+ size_t size;
+ struct CredentialEntry *cdata;
+
+ size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
+ *data = GNUNET_malloc (size);
+ cdata = (struct CredentialEntry*)*data;
+ cdata->subject_key = cred->subject_key;
+ cdata->issuer_key = cred->issuer_key;
+ cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
+ cdata->signature = cred->signature;
+ cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
+ cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
+ cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+ GNUNET_memcpy (&cdata[1],
+ cred->issuer_attribute,
+ strlen (cred->issuer_attribute));
+
+ if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
+ &cdata->purpose,
+ &cdata->signature,
+ &cdata->issuer_key))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Invalid credential\n");
+ //return NULL;
+ }
+ return size;
+}
+
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_deserialize (const char* data,
+ size_t data_size)
+{
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ struct CredentialEntry *cdata;
+ char *issuer_attribute;
+
+ if (data_size < sizeof (struct CredentialEntry))
+ return NULL;
+ cdata = (struct CredentialEntry*)data;
+ if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
+ &cdata->purpose,
+ &cdata->signature,
+ &cdata->issuer_key))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Invalid credential\n");
+ //return NULL;
+ }
+ issuer_attribute = (char*)&cdata[1];
+
+ cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
+
+ cred->issuer_key = cdata->issuer_key;
+ cred->subject_key = cdata->subject_key;
+ GNUNET_memcpy (&cred[1],
+ issuer_attribute,
+ ntohl (cdata->issuer_attribute_len));
+ cred->signature = cdata->signature;
+ cred->issuer_attribute = (char*)&cred[1];
+ cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
+ return cred;
+}
+
+
+/* end of credential_serialization.c */
--- /dev/null
+/*
+ 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 General Public License as published
+ by the Free Software Foundation; either version 3, 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+/**
+ * @file credential/credential_serialization.h
+ * @brief API to serialize and deserialize delegation chains
+ * and credentials
+ * @author Martin Schanzenbach
+ */
+#ifndef CREDENTIAL_SERIALIZATION_H
+#define CREDENTIAL_SERIALIZATION_H
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_credential_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_CREDENTIAL_Delegation
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
+ const struct GNUNET_CREDENTIAL_DelegationSet *dsr);
+
+/**
+ * Serizalize the given delegation record entries
+ *
+ * @param d_count number of delegation chain entries
+ * @param dsr array of #GNUNET_CREDENTIAL_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_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
+ const struct GNUNET_CREDENTIAL_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_CREDENTIAL_delegation_set_deserialize (size_t len,
+ const char *src,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_DelegationSet *dsr);
+
+ /**
+ * Calculate how many bytes we will need to serialize
+ * the given delegation chain and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @return the required size to serialize
+ */
+ size_t
+ GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
+ const struct GNUNET_CREDENTIAL_Delegation *dd,
+ unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *cd);
+
+ /**
+ * Serizalize the given delegation chain entries and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_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_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
+ const struct GNUNET_CREDENTIAL_Delegation *dd,
+ unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *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 credential entries
+ * @param cd where to put the credential data
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+ int
+ GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
+ const char *src,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_Delegation *dd,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cd);
+ size_t
+ GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *cd);
+
+ssize_t
+GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *cd,
+ size_t dest_size,
+ char *dest);
+
+
+int
+GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
+ const char *src,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cd);
+
+
+int
+GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
+ char **data);
+
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_deserialize (const char* data,
+ size_t data_size);
+#endif
+/* end of credential_serialization.h */
--- /dev/null
+/*
+ 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 General Public License as published
+ by the Free Software Foundation; either version 3, 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file gnunet-credential.c
+ * @brief command line tool to access command line Credential service
+ * @author Adnan Husain
+ */
+#include "platform.h"
+#include <gnunet_util_lib.h>
+#include <gnunet_credential_service.h>
+#include <gnunet_gnsrecord_lib.h>
+#include "credential_misc.h"
+#include "credential_serialization.h"
+
+/**
+ * Configuration we are using.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * EgoLookup
+ */
+static struct GNUNET_IDENTITY_EgoLookup *el;
+
+/**
+ * Handle to Credential service.
+ */
+static struct GNUNET_CREDENTIAL_Handle *credential;
+
+/**
+ * Desired timeout for the lookup (default is no timeout).
+ */
+static struct GNUNET_TIME_Relative timeout;
+
+/**
+ * Handle to verify request
+ */
+static struct GNUNET_CREDENTIAL_Request *verify_request;
+
+/**
+ * Handle to collect request
+ */
+static struct GNUNET_CREDENTIAL_Request *collect_request;
+
+/**
+ * Task scheduled to handle timeout.
+ */
+static struct GNUNET_SCHEDULER_Task *tt;
+
+/**
+ * Subject pubkey string
+ */
+static char *subject_key;
+
+/**
+ * Subject credential string
+ */
+static char *subject_credential;
+
+/**
+ * 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;
+
+/**
+ * Issue mode
+ */
+static int create_cred;
+
+/**
+ * Collect mode
+ */
+static int collect;
+
+/**
+ * Task run on shutdown. Cleans up everything.
+ *
+ * @param cls unused
+ */
+static void
+do_shutdown (void *cls)
+{
+ if (NULL != verify_request)
+ {
+ GNUNET_CREDENTIAL_request_cancel (verify_request);
+ verify_request = NULL;
+ }
+ if (NULL != credential)
+ {
+ GNUNET_CREDENTIAL_disconnect (credential);
+ credential = NULL;
+ }
+ if (NULL != tt)
+ {
+ GNUNET_SCHEDULER_cancel (tt);
+ tt = NULL;
+ }
+}
+
+
+/**
+ * Task run on timeout. Triggers shutdown.
+ *
+ * @param cls unused
+ */
+static void
+do_timeout (void *cls)
+{
+ tt = NULL;
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+/**
+ * Function called with the result of a Credential lookup.
+ *
+ * @param cls the 'const char *' name that was resolved
+ * @param cd_count number of records returned
+ * @param cd array of @a cd_count records with the results
+ */
+static void
+handle_collect_result (void *cls,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_Delegation *dc,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cred)
+{
+ int i;
+ char* line;
+
+ verify_request = NULL;
+ if (NULL != cred)
+ {
+ for (i=0;i<c_count;i++)
+ {
+ line = GNUNET_CREDENTIAL_credential_to_string (&cred[i]);
+ printf ("%s\n",
+ line);
+ GNUNET_free (line);
+ }
+ }
+
+
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * Function called with the result of a Credential lookup.
+ *
+ * @param cls the 'const char *' name that was resolved
+ * @param cd_count number of records returned
+ * @param cd array of @a cd_count records with the results
+ */
+static void
+handle_verify_result (void *cls,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_Delegation *dc,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cred)
+{
+ int i;
+ char* iss_key;
+ char* sub_key;
+
+ verify_request = NULL;
+ if (NULL == cred)
+ printf ("Failed.\n");
+ 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("\nCredentials:\n");
+ for (i=0;i<c_count;i++)
+ {
+ iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].issuer_key);
+ sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].subject_key);
+ printf ("%s.%s <- %s\n",
+ iss_key, cred[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;
+ struct GNUNET_CREDENTIAL_Credential *crd;
+ struct GNUNET_TIME_Absolute etime_abs;
+ struct GNUNET_TIME_Relative etime_rel;
+ char *res;
+
+ 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_CREDENTIAL_collect(credential,
+ &issuer_pkey,
+ issuer_attr, //TODO argument
+ privkey,
+ &handle_collect_result,
+ NULL);
+ return;
+ }
+
+ //Else issue
+
+ if (NULL == expiration)
+ {
+ fprintf (stderr,
+ "Please specify a TTL\n");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration,
+ &etime_rel))
+ {
+ etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
+ } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration,
+ &etime_abs))
+ {
+ fprintf (stderr,
+ "%s is not a valid ttl!\n",
+ expiration);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
+
+ privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
+ GNUNET_free_non_null (ego_name);
+ ego_name = NULL;
+ crd = GNUNET_CREDENTIAL_credential_issue (privkey,
+ &subject_pkey,
+ issuer_attr,
+ &etime_abs);
+
+ res = GNUNET_CREDENTIAL_credential_to_string (crd);
+ GNUNET_free (crd);
+ printf ("%s\n", res);
+ 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);
+
+ if (GNUNET_YES == collect) {
+ if (NULL == issuer_key)
+ {
+ fprintf (stderr,
+ _("Issuer public key not well-formed\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+
+ }
+
+ credential = GNUNET_CREDENTIAL_connect (cfg);
+
+ if (NULL == credential)
+ {
+ fprintf (stderr,
+ _("Failed to connect to CREDENTIAL\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ }
+ if (NULL == issuer_attr)
+ {
+ fprintf (stderr,
+ _("You must provide issuer the attribute\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ }
+
+ 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_key)
+ {
+ fprintf (stderr,
+ _("Subject public key needed\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+
+ }
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_key,
+ strlen (subject_key),
+ &subject_pkey))
+ {
+ fprintf (stderr,
+ _("Subject public key `%s' is not well-formed\n"),
+ subject_key);
+ 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 ();
+ }
+ credential = GNUNET_CREDENTIAL_connect (cfg);
+
+ if (NULL == credential)
+ {
+ fprintf (stderr,
+ _("Failed to connect to CREDENTIAL\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ }
+ if (NULL == issuer_attr || NULL == subject_credential)
+ {
+ fprintf (stderr,
+ _("You must provide issuer and subject attributes\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ }
+
+ //Subject credentials are comma separated
+ char *tmp = GNUNET_strdup (subject_credential);
+ char *tok = strtok (tmp, ",");
+ if (NULL == tok)
+ {
+ fprintf (stderr,
+ "Invalid subject credentials\n");
+ GNUNET_free (tmp);
+ GNUNET_SCHEDULER_shutdown ();
+ }
+ int count = 1;
+ int i;
+ while (NULL != (tok = strtok(NULL, ",")))
+ count++;
+ struct GNUNET_CREDENTIAL_Credential credentials[count];
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ GNUNET_free (tmp);
+ tmp = GNUNET_strdup (subject_credential);
+ tok = strtok (tmp, ",");
+ for (i=0;i<count;i++)
+ {
+ cred = GNUNET_CREDENTIAL_credential_from_string (tok);
+ GNUNET_memcpy (&credentials[i],
+ cred,
+ sizeof (struct GNUNET_CREDENTIAL_Credential));
+ credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
+ tok = strtok(NULL, ",");
+ GNUNET_free (cred);
+ }
+
+ verify_request = GNUNET_CREDENTIAL_verify(credential,
+ &issuer_pkey,
+ issuer_attr, //TODO argument
+ &subject_pkey,
+ count,
+ credentials,
+ &handle_verify_result,
+ NULL);
+ for (i=0;i<count;i++)
+ {
+ GNUNET_free ((char*)credentials[i].issuer_attribute);
+ }
+ } else if (GNUNET_YES == create_cred) {
+ if (NULL == ego_name)
+ {
+ fprintf (stderr,
+ _("Issuer ego required\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+
+ }
+ el = GNUNET_IDENTITY_ego_lookup (cfg,
+ ego_name,
+ &identity_cb,
+ (void *) cfg);
+ return;
+ } 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 ('I',
+ "issue",
+ gettext_noop ("create credential"),
+ &create_cred),
+ 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"),
+ &subject_key),
+ GNUNET_GETOPT_option_string ('b',
+ "credential",
+ "CRED",
+ gettext_noop ("The name of the credential presented by the subject"),
+ &subject_credential),
+ 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 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"),
+ &expiration),
+ GNUNET_GETOPT_option_flag ('g',
+ "collect",
+ gettext_noop ("collect credentials"),
+ &collect),
+ GNUNET_GETOPT_OPTION_END
+ };
+ int ret;
+
+ timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+ if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+ return 2;
+
+ GNUNET_log_setup ("gnunet-credential", "WARNING", NULL);
+ ret =
+ (GNUNET_OK ==
+ GNUNET_PROGRAM_run (argc, argv, "gnunet-credential",
+ _("GNUnet credential resolver tool"),
+ options,
+ &run, NULL)) ? 0 : 1;
+ GNUNET_free ((void*) argv);
+ return ret;
+}
+
+/* end of gnunet-credential.c */
--- /dev/null
+/*
+ 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 General Public License as published
+ by the Free Software Foundation; either version 3, 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file gns/gnunet-service-credential.c
+ * @brief GNU Credential Service (main service)
+ * @author Adnan Husain
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_statistics_service.h"
+#include "credential.h"
+#include "credential_serialization.h"
+#include "gnunet_protocols.h"
+#include "gnunet_signatures.h"
+
+#include <gnunet_dnsparser_lib.h>
+#include <gnunet_identity_service.h>
+#include <gnunet_gnsrecord_lib.h>
+#include <gnunet_namestore_service.h>
+#include <gnunet_gns_service.h>
+
+
+#define GNUNET_CREDENTIAL_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 CredentialRecordEntry
+{
+ /**
+ * DLL
+ */
+ struct CredentialRecordEntry *next;
+
+ /**
+ * DLL
+ */
+ struct CredentialRecordEntry *prev;
+
+ /**
+ * Number of references in delegation chains
+ */
+ uint32_t refcount;
+
+ /**
+ * Payload
+ */
+ struct GNUNET_CREDENTIAL_Credential *credential;
+};
+
+/**
+ * DLL used for delegations
+ * Used for OR delegations
+ */
+struct DelegationQueueEntry
+{
+ /**
+ * DLL
+ */
+ struct DelegationQueueEntry *next;
+
+ /**
+ * DLL
+ */
+ struct DelegationQueueEntry *prev;
+
+ /**
+ * Sets under this Queue
+ */
+ struct DelegationSetQueueEntry *set_entries_head;
+
+ /**
+ * Sets under this Queue
+ */
+ struct DelegationSetQueueEntry *set_entries_tail;
+
+ /**
+ * Parent set
+ */
+ struct DelegationSetQueueEntry *parent_set;
+
+ /**
+ * Required solutions
+ */
+ uint32_t required_solutions;
+};
+
+/**
+ * DLL for delegation sets
+ * Used for AND delegation set
+ */
+struct DelegationSetQueueEntry
+{
+ /**
+ * DLL
+ */
+ struct DelegationSetQueueEntry *next;
+
+ /**
+ * DLL
+ */
+ struct DelegationSetQueueEntry *prev;
+
+ /**
+ * GNS handle
+ */
+ struct GNUNET_GNS_LookupRequest *lookup_request;
+
+ /**
+ * 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;
+
+};
+
+
+/**
+ * Handle to a lookup operation from api
+ */
+struct VerifyRequestHandle
+{
+
+ /**
+ * 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;
+
+ /**
+ * GNS handle
+ */
+ struct GNUNET_GNS_LookupRequest *lookup_request;
+
+ /**
+ * Size of delegation tree
+ */
+ uint32_t delegation_chain_size;
+
+ /**
+ * Children of this attribute
+ */
+ struct DelegationChainEntry *delegation_chain_head;
+
+ /**
+ * Children of this attribute
+ */
+ struct DelegationChainEntry *delegation_chain_tail;
+
+ /**
+ * Issuer public key
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * Issuer attribute
+ */
+ char *issuer_attribute;
+
+ /**
+ * Subject public key
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * Credential DLL
+ */
+ struct CredentialRecordEntry *cred_chain_head;
+
+ /**
+ * Credential DLL
+ */
+ struct CredentialRecordEntry *cred_chain_tail;
+
+ /**
+ * Credential DLL size
+ */
+ uint32_t cred_chain_size;
+
+ /**
+ * Root Delegation Set
+ */
+ struct DelegationSetQueueEntry *root_set;
+
+ /**
+ * Current Delegation Pointer
+ */
+ struct DelegationQueueEntry *current_delegation;
+
+ /**
+ * request id
+ */
+ uint32_t request_id;
+
+ /**
+ * Pending lookups
+ */
+ uint64_t pending_lookups;
+
+ /**
+ * Credential iterator
+ */
+ struct GNUNET_NAMESTORE_ZoneIterator *cred_collection_iter;
+
+ /**
+ * Collect task
+ */
+ struct GNUNET_SCHEDULER_Task *collect_next_task;
+
+};
+
+
+/**
+ * Head of the DLL.
+ */
+static struct VerifyRequestHandle *vrh_head;
+
+/**
+ * Tail of the DLL.
+ */
+static struct VerifyRequestHandle *vrh_tail;
+
+/**
+ * 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
+cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry)
+{
+ struct DelegationQueueEntry *dq_entry;
+ struct DelegationSetQueueEntry *child;
+
+ if (NULL == ds_entry)
+ return;
+
+ for (dq_entry = ds_entry->queue_entries_head;
+ NULL != dq_entry;
+ dq_entry = ds_entry->queue_entries_head)
+ {
+ GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
+ ds_entry->queue_entries_tail,
+ dq_entry);
+ for (child = dq_entry->set_entries_head;
+ NULL != child;
+ child = dq_entry->set_entries_head)
+ {
+ GNUNET_CONTAINER_DLL_remove (dq_entry->set_entries_head,
+ dq_entry->set_entries_tail,
+ child);
+ cleanup_delegation_set (child);
+ }
+ GNUNET_free (dq_entry);
+ }
+ if (NULL != ds_entry->issuer_key)
+ GNUNET_free (ds_entry->issuer_key);
+ if (NULL != ds_entry->lookup_attribute)
+ GNUNET_free (ds_entry->lookup_attribute);
+ if (NULL != ds_entry->issuer_attribute)
+ GNUNET_free (ds_entry->issuer_attribute);
+ if (NULL != ds_entry->unresolved_attribute_delegation)
+ GNUNET_free (ds_entry->unresolved_attribute_delegation);
+ if (NULL != ds_entry->attr_trailer)
+ GNUNET_free (ds_entry->attr_trailer);
+ if (NULL != ds_entry->lookup_request)
+ {
+ GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
+ ds_entry->lookup_request = NULL;
+ }
+ if (NULL != ds_entry->delegation_chain_entry)
+ {
+ if (NULL != ds_entry->delegation_chain_entry->subject_attribute)
+ GNUNET_free (ds_entry->delegation_chain_entry->subject_attribute);
+ if (NULL != ds_entry->delegation_chain_entry->issuer_attribute)
+ GNUNET_free (ds_entry->delegation_chain_entry->issuer_attribute);
+ GNUNET_free (ds_entry->delegation_chain_entry);
+ }
+ GNUNET_free (ds_entry);
+}
+
+static void
+cleanup_handle (struct VerifyRequestHandle *vrh)
+{
+ struct CredentialRecordEntry *cr_entry;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Cleaning up...\n");
+ if (NULL != vrh->lookup_request)
+ {
+ GNUNET_GNS_lookup_cancel (vrh->lookup_request);
+ vrh->lookup_request = NULL;
+ }
+ cleanup_delegation_set (vrh->root_set);
+ if (NULL != vrh->issuer_attribute)
+ GNUNET_free (vrh->issuer_attribute);
+ for (cr_entry = vrh->cred_chain_head;
+ NULL != vrh->cred_chain_head;
+ cr_entry = vrh->cred_chain_head)
+ {
+ GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
+ vrh->cred_chain_tail,
+ cr_entry);
+ if (NULL != cr_entry->credential);
+ GNUNET_free (cr_entry->credential);
+ GNUNET_free (cr_entry);
+ }
+ GNUNET_free (vrh);
+}
+
+/**
+ * Task run during shutdown.
+ *
+ * @param cls unused
+ * @param tc unused
+ */
+static void
+shutdown_task (void *cls)
+{
+ struct VerifyRequestHandle *vrh;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Shutting down!\n");
+
+ while (NULL != (vrh = vrh_head))
+ {
+ //CREDENTIAL_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;
+ }
+
+}
+
+
+
+/**
+ * Send.
+ *
+ * @param handle the handle to the request
+ */
+static void
+send_lookup_response (struct VerifyRequestHandle *vrh)
+{
+ struct GNUNET_MQ_Envelope *env;
+ struct DelegationChainResultMessage *rmsg;
+ struct DelegationChainEntry *dce;
+ struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
+ struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
+ struct CredentialRecordEntry *cd;
+ struct CredentialRecordEntry *tmp;
+ size_t size;
+ int i;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending response\n");
+ dce = vrh->delegation_chain_head;
+ for (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 credentials not needed
+ */
+ for (cd = vrh->cred_chain_head; NULL != cd;)
+ {
+ if (cd->refcount > 0)
+ {
+ cd = cd->next;
+ continue;
+ }
+ tmp = cd;
+ cd = cd->next;
+ GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
+ vrh->cred_chain_tail,
+ tmp);
+ GNUNET_free (tmp->credential);
+ GNUNET_free (tmp);
+ vrh->cred_chain_size--;
+ }
+
+ /**
+ * Get serialized record data
+ * Append at the end of rmsg
+ */
+ cd = vrh->cred_chain_head;
+ for (i=0;i<vrh->cred_chain_size;i++)
+ {
+ cred[i].issuer_key = cd->credential->issuer_key;
+ cred[i].subject_key = cd->credential->subject_key;
+ cred[i].issuer_attribute_len = strlen(cd->credential->issuer_attribute)+1;
+ cred[i].issuer_attribute = cd->credential->issuer_attribute;
+ cred[i].expiration = cd->credential->expiration;
+ cred[i].signature = cd->credential->signature;
+ cd = cd->next;
+ }
+ size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->delegation_chain_size,
+ dd,
+ vrh->cred_chain_size,
+ cred);
+ env = GNUNET_MQ_msg_extra (rmsg,
+ size,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
+ //Assign id so that client can find associated request
+ rmsg->id = vrh->request_id;
+ rmsg->d_count = htonl (vrh->delegation_chain_size);
+ rmsg->c_count = htonl (vrh->cred_chain_size);
+
+ if (0 < vrh->cred_chain_size)
+ rmsg->cred_found = htonl (GNUNET_YES);
+ else
+ rmsg->cred_found = htonl (GNUNET_NO);
+
+ GNUNET_assert (-1 !=
+ GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->delegation_chain_size,
+ dd,
+ vrh->cred_chain_size,
+ cred,
+ 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 void
+backward_resolution (void* cls,
+ uint32_t rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+
+ struct VerifyRequestHandle *vrh;
+ const struct GNUNET_CREDENTIAL_DelegationRecord *sets;
+ struct CredentialRecordEntry *cred_pointer;
+ struct DelegationSetQueueEntry *current_set;
+ struct DelegationSetQueueEntry *ds_entry;
+ struct DelegationSetQueueEntry *tmp_set;
+ struct DelegationQueueEntry *dq_entry;
+ char *expanded_attr;
+ char *lookup_attribute;
+ int i;
+ int j;
+
+
+ current_set = cls;
+ current_set->lookup_request = NULL;
+ vrh = current_set->handle;
+ vrh->pending_lookups--;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Got %d attrs\n", rd_count);
+
+ // Each OR
+ for (i=0; i < rd_count; i++)
+ {
+ if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
+ continue;
+
+ sets = rd[i].data;
+ struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)];
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Found new attribute delegation with %d sets. Creating new Job...\n",
+ ntohl (sets->set_count));
+
+ if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size),
+ (const char*)&sets[1],
+ ntohl(sets->set_count),
+ set))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "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 (j=0; j<ntohl(sets->set_count); j++)
+ {
+ ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
+ if (NULL != current_set->attr_trailer)
+ {
+ if (0 == set[j].subject_attribute_len)
+ {
+ GNUNET_asprintf (&expanded_attr,
+ "%s",
+ current_set->attr_trailer);
+
+ } else {
+ GNUNET_asprintf (&expanded_attr,
+ "%s.%s",
+ set[j].subject_attribute,
+ current_set->attr_trailer);
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Expanded to %s\n", expanded_attr);
+ ds_entry->unresolved_attribute_delegation = expanded_attr;
+ } else {
+ if (0 != set[j].subject_attribute_len)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Not Expanding %s\n", set[j].subject_attribute);
+ ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute);
+ }
+ }
+
+ //Add a credential chain entry
+ ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
+ ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
+ ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
+ GNUNET_memcpy (ds_entry->issuer_key,
+ &set[j].subject_key,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ if (0 < set[j].subject_attribute_len)
+ ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute);
+ ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
+ ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute);
+
+ ds_entry->parent_queue_entry = dq_entry; //current_delegation;
+ GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head,
+ dq_entry->set_entries_tail,
+ ds_entry);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Checking for cred match\n");
+ /**
+ * Check if this delegation already matches one of our credentials
+ */
+ for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL;
+ cred_pointer = cred_pointer->next)
+ {
+ if(0 != memcmp (&set->subject_key,
+ &cred_pointer->credential->issuer_key,
+ sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ continue;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Checking if %s matches %s\n",
+ ds_entry->unresolved_attribute_delegation,
+ cred_pointer->credential->issuer_attribute);
+
+ if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
+ cred_pointer->credential->issuer_attribute))
+ continue;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Found issuer\n");
+ cred_pointer->refcount++;
+ //Backtrack
+ for (tmp_set = ds_entry;
+ NULL != tmp_set->parent_queue_entry;
+ tmp_set = tmp_set->parent_queue_entry->parent_set)
+ {
+ tmp_set->parent_queue_entry->required_solutions--;
+ if (NULL != tmp_set->delegation_chain_entry)
+ {
+ vrh->delegation_chain_size++;
+ GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
+ vrh->delegation_chain_tail,
+ tmp_set->delegation_chain_entry);
+ }
+ if (0 < tmp_set->parent_queue_entry->required_solutions)
+ break;
+ }
+
+ if (NULL == tmp_set->parent_queue_entry)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "All solutions found\n");
+ //Found match
+ send_lookup_response (vrh);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Not all solutions found yet.\n");
+ continue;
+
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Building new lookup request from %s\n",
+ ds_entry->unresolved_attribute_delegation);
+ //Continue with backward resolution
+ char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1];
+ strcpy (issuer_attribute_name,
+ ds_entry->unresolved_attribute_delegation);
+ char *next_attr = strtok (issuer_attribute_name, ".");
+ GNUNET_asprintf (&lookup_attribute,
+ "%s.gnu",
+ next_attr);
+ GNUNET_asprintf (&ds_entry->lookup_attribute,
+ "%s",
+ next_attr);
+ if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation))
+ {
+ ds_entry->attr_trailer = NULL;
+ } else {
+ next_attr += strlen (next_attr) + 1;
+ ds_entry->attr_trailer = GNUNET_strdup (next_attr);
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Looking up %s\n", ds_entry->lookup_attribute);
+ if (NULL != ds_entry->attr_trailer)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s still to go...\n", ds_entry->attr_trailer);
+
+ vrh->pending_lookups++;
+ ds_entry->handle = vrh;
+ ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
+ lookup_attribute,
+ ds_entry->issuer_key, //issuer_key,
+ GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
+ GNUNET_GNS_LO_DEFAULT,
+ &backward_resolution,
+ ds_entry);
+ GNUNET_free (lookup_attribute);
+ }
+ }
+
+ 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)
+ * @param rd_count the number of records in @a rd
+ * @param rd the record data
+ */
+static void
+delegation_chain_resolution_start (void* cls)
+{
+ struct VerifyRequestHandle *vrh = cls;
+ struct DelegationSetQueueEntry *ds_entry;
+ struct CredentialRecordEntry *cr_entry;
+ vrh->lookup_request = NULL;
+
+ if (0 == vrh->cred_chain_size)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No credentials found\n");
+ send_lookup_response (vrh);
+ return;
+ }
+
+ for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = cr_entry->next)
+ {
+ if (0 != memcmp (&cr_entry->credential->issuer_key,
+ &vrh->issuer_key,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ continue;
+ if (0 != strcmp (cr_entry->credential->issuer_attribute, vrh->issuer_attribute))
+ continue;
+ cr_entry->refcount++;
+ //Found match prematurely
+ send_lookup_response (vrh);
+ return;
+
+ }
+
+ /**
+ * 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)];
+ strcpy (issuer_attribute_name,
+ vrh->issuer_attribute);
+ strcpy (issuer_attribute_name + strlen (vrh->issuer_attribute),
+ ".gnu");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Looking up %s\n", issuer_attribute_name);
+ ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
+ ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
+ memcpy (ds_entry->issuer_key,
+ &vrh->issuer_key,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
+ ds_entry->handle = vrh;
+ ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
+ vrh->root_set = ds_entry;
+ vrh->pending_lookups = 1;
+ //Start with backward resolution
+ 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);
+}
+
+/**
+ * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY message
+ *
+ * @param cls client sending the message
+ * @param v_msg message of type `struct VerifyMessage`
+ * @return #GNUNET_OK if @a v_msg is well-formed
+ */
+static int
+check_verify (void *cls,
+ const struct VerifyMessage *v_msg)
+{
+ size_t msg_size;
+ const char* attr;
+
+ msg_size = ntohs (v_msg->header.size);
+ if (msg_size < sizeof (struct VerifyMessage))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ attr = (const char *) &v_msg[1];
+
+ if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+/**
+ * Handle Credential verification requests from client
+ *
+ * @param cls the closure
+ * @param client the client
+ * @param message the message
+ */
+static void
+handle_verify (void *cls,
+ const struct VerifyMessage *v_msg)
+{
+ struct VerifyRequestHandle *vrh;
+ struct GNUNET_SERVICE_Client *client = cls;
+ struct CredentialRecordEntry *cr_entry;
+ uint32_t credentials_count;
+ uint32_t credential_data_size;
+ int i;
+ char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+ char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+ char *attrptr = attr;
+ char *credential_data;
+ const char *utf_in;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_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);
+ 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);
+ if (NULL == issuer_attribute)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No issuer attribute provided!\n");
+ send_lookup_response (vrh);
+ return;
+ }
+ /**
+ * First, collect credentials
+ * TODO: cleanup!
+ */
+ credentials_count = ntohl(v_msg->c_count);
+ credential_data_size = ntohs (v_msg->header.size)
+ - sizeof (struct VerifyMessage)
+ - ntohs (v_msg->issuer_attribute_len)
+ - 1;
+ struct GNUNET_CREDENTIAL_Credential credentials[credentials_count];
+ credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
+ if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize (credential_data_size,
+ credential_data,
+ credentials_count,
+ credentials))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Cannot deserialize credentials!\n");
+ send_lookup_response (vrh);
+ return;
+ }
+
+ for (i=0;i<credentials_count;i++) {
+ cr_entry = GNUNET_new (struct CredentialRecordEntry);
+ cr_entry->credential = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) +
+ credentials[i].issuer_attribute_len);
+ GNUNET_memcpy (cr_entry->credential,
+ &credentials[i],
+ sizeof (struct GNUNET_CREDENTIAL_Credential));
+ GNUNET_memcpy (&cr_entry->credential[1],
+ credentials[i].issuer_attribute,
+ credentials[i].issuer_attribute_len);
+ cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1];
+ GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
+ vrh->cred_chain_tail,
+ cr_entry);
+ vrh->cred_chain_size++;
+ }
+
+ delegation_chain_resolution_start (vrh);
+
+}
+
+/**
+ * We encountered an error while collecting
+ */
+static void
+handle_cred_collection_error_cb (void *cls)
+{
+ struct VerifyRequestHandle *vrh = cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Got disconnected from namestore database.\n");
+ vrh->cred_collection_iter = NULL;
+ send_lookup_response (vrh);
+}
+
+static void
+collect_next (void *cls)
+{
+ struct VerifyRequestHandle *vrh = cls;
+ vrh->collect_next_task = NULL;
+ GNUNET_assert (NULL != vrh->cred_collection_iter);
+ GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter);
+}
+
+/**
+ * Store credential
+ */
+static void
+handle_cred_collection_cb (void *cls,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
+ const char *label,
+ unsigned int rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+ struct VerifyRequestHandle *vrh = cls;
+ struct GNUNET_CREDENTIAL_Credential *crd;
+ struct CredentialRecordEntry *cr_entry;
+ int cred_record_count;
+ int i;
+
+ cred_record_count = 0;
+ for (i=0; i < rd_count; i++)
+ {
+ if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
+ continue;
+ cred_record_count++;
+ crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
+ rd[i].data_size);
+ if (NULL == crd)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Invalid credential found\n");
+ continue;
+ }
+ cr_entry = GNUNET_new (struct CredentialRecordEntry);
+ cr_entry->credential = crd;
+ GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
+ vrh->cred_chain_tail,
+ cr_entry);
+ vrh->cred_chain_size++;
+ }
+ vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next,
+ vrh);
+}
+
+/**
+ * We encountered an error while collecting
+ */
+static void
+handle_cred_collection_finished_cb (void *cls)
+{
+ struct VerifyRequestHandle *vrh = cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Done collecting credentials.\n");
+ vrh->cred_collection_iter = NULL;
+ delegation_chain_resolution_start (vrh);
+}
+
+/**
+ * Handle Credential collection requests from client
+ *
+ * @param cls the closure
+ * @param client the client
+ * @param message the message
+ */
+static void
+handle_collect (void *cls,
+ const struct CollectMessage *c_msg)
+{
+ char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+ char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+ struct VerifyRequestHandle *vrh;
+ struct GNUNET_SERVICE_Client *client = cls;
+ char *attrptr = attr;
+ const char *utf_in;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received COLLECT message\n");
+
+ utf_in = (const char *) &c_msg[1];
+ GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
+
+ GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
+ issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
+ vrh = GNUNET_new (struct VerifyRequestHandle);
+ GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
+ vrh->client = client;
+ vrh->request_id = c_msg->id;
+ vrh->issuer_key = c_msg->issuer_key;
+ GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key,
+ &vrh->subject_key);
+ vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
+
+ if (NULL == issuer_attribute)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No issuer attribute provided!\n");
+ send_lookup_response (vrh);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Getting credentials for subject\n");
+ /**
+ * First, get attribute from subject
+ */
+ vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore,
+ &c_msg->subject_key,
+ &handle_cred_collection_error_cb,
+ vrh,
+ &handle_cred_collection_cb,
+ vrh,
+ &handle_cred_collection_finished_cb,
+ vrh);
+}
+
+
+/**
+ * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT message
+ *
+ * @param cls client sending the message
+ * @param v_msg message of type `struct CollectMessage`
+ * @return #GNUNET_OK if @a v_msg is well-formed
+ */
+static int
+check_collect (void *cls,
+ const struct CollectMessage *c_msg)
+{
+ size_t msg_size;
+ const char* attr;
+
+ msg_size = ntohs (c_msg->header.size);
+ if (msg_size < sizeof (struct CollectMessage))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ attr = (const char *) &c_msg[1];
+
+ if ( ('\0' != attr[ntohs(c_msg->header.size) - sizeof (struct CollectMessage) - 1]) ||
+ (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+/**
+ * One of our clients disconnected, clean up after it.
+ *
+ * @param cls NULL
+ * @param client the client that disconnected
+ */
+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);
+}
+
+/**
+ * Add a client to our list of active clients.
+ *
+ * @param cls NULL
+ * @param client client to add
+ * @param mq message queue for @a client
+ * @return this 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 server the initialized server
+ * @param c configuration to use
+ */
+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 ("credential", c);
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
+}
+
+
+/**
+ * Define "main" method using service macro
+ */
+GNUNET_SERVICE_MAIN
+("credential",
+ GNUNET_SERVICE_OPTION_NONE,
+ &run,
+ &client_connect_cb,
+ &client_disconnect_cb,
+ NULL,
+ GNUNET_MQ_hd_var_size (verify,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
+ struct VerifyMessage,
+ NULL),
+ GNUNET_MQ_hd_var_size (collect,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT,
+ struct CollectMessage,
+ NULL),
+ GNUNET_MQ_handler_end());
+
+/* end of gnunet-service-credential.c */
--- /dev/null
+/*
+ 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 General Public License as published
+ by the Free Software Foundation; either version 3, 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file credential/plugin_gnsrecord_credential.c
+ * @brief gnsrecord plugin to provide the API for CREDENTIAL records
+ * @author Adnan Husain
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_gnsrecord_lib.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_gnsrecord_plugin.h"
+#include "gnunet_signatures.h"
+#include "credential_serialization.h"
+#include "credential_misc.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 *
+credential_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_CREDENTIAL_DelegationRecord sets;
+ char *attr_str;
+ char *subject_pkey;
+ char *tmp_str;
+ int i;
+ if (data_size < sizeof (struct GNUNET_CREDENTIAL_DelegationRecord))
+ return NULL; /* malformed */
+ memcpy (&sets,
+ data,
+ sizeof (sets));
+ cdata = data;
+ struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets.set_count)];
+ if (GNUNET_OK != GNUNET_CREDENTIAL_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);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%d len attr\n", set[i].subject_attribute_len);
+ 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_CREDENTIAL:
+ {
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ char *cred_str;
+
+ cred = GNUNET_CREDENTIAL_credential_deserialize (data,
+ data_size);
+ cred_str = GNUNET_CREDENTIAL_credential_to_string (cred);
+ GNUNET_free (cred);
+ return cred_str;
+ }
+ case GNUNET_GNSRECORD_TYPE_POLICY:
+ {
+ return GNUNET_strndup (data,data_size);
+ }
+ 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
+credential_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_CREDENTIAL_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_CREDENTIAL_DelegationRecord);
+ while (NULL != token)
+ {
+ 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;
+ }
+ if (1 == matches) {
+ tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet);
+ } else if (2 == matches) {
+ tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet) + strlen (attr_str) + 1;
+ }
+ entries++;
+ token = strtok (NULL, ",");
+ }
+ GNUNET_free (tmp_str);
+ tmp_str = GNUNET_strdup (s);
+ token = strtok (tmp_str, ",");
+ struct GNUNET_CREDENTIAL_DelegationSet set[entries];
+ for (i=0;i<entries;i++)
+ {
+ matches = SSCANF (token,
+ "%s %s",
+ subject_pkey,
+ attr_str);
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
+ strlen (subject_pkey),
+ &set[i].subject_key);
+ if (2 == matches) {
+ set[i].subject_attribute_len = strlen (attr_str) + 1;
+ set[i].subject_attribute = GNUNET_strdup (attr_str);
+ }
+ token = strtok (NULL , ",");
+ }
+ tmp_data_size = GNUNET_CREDENTIAL_delegation_set_get_size (entries,
+ set);
+
+ if (-1 == tmp_data_size)
+ return GNUNET_SYSERR;
+ *data_size += tmp_data_size;
+ *data = sets = GNUNET_malloc (*data_size);
+ GNUNET_CREDENTIAL_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_CREDENTIAL:
+ {
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ cred = GNUNET_CREDENTIAL_credential_from_string (s);
+
+ *data_size = GNUNET_CREDENTIAL_credential_serialize (cred,
+ (char**)data);
+ return GNUNET_OK;
+ }
+ case GNUNET_GNSRECORD_TYPE_POLICY:
+ {
+ *data_size = strlen (s);
+ *data = GNUNET_strdup (s);
+ 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[] = {
+ { "CRED", GNUNET_GNSRECORD_TYPE_CREDENTIAL },
+ { "ATTR", GNUNET_GNSRECORD_TYPE_ATTRIBUTE },
+ { "POLICY", GNUNET_GNSRECORD_TYPE_POLICY },
+ { 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
+credential_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 *
+credential_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_credential_init (void *cls)
+{
+ struct GNUNET_GNSRECORD_PluginFunctions *api;
+
+ api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
+ api->value_to_string = &credential_value_to_string;
+ api->string_to_value = &credential_string_to_value;
+ api->typename_to_number = &credential_typename_to_number;
+ api->number_to_typename = &credential_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_credential_done (void *cls)
+{
+ struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
+
+ GNUNET_free (api);
+ return NULL;
+}
+
+/* end of plugin_gnsrecord_credential.c */
--- /dev/null
+/*
+ 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 General Public License as published
+ by the Free Software Foundation; either version 3, 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+/**
+ * @author Martin Schanzenbach
+ * @file gns/plugin_rest_credential.c
+ * @brief GNUnet CREDENTIAL REST plugin
+ *
+ */
+
+#include "platform.h"
+#include "gnunet_rest_plugin.h"
+#include <gnunet_identity_service.h>
+#include <gnunet_gnsrecord_lib.h>
+#include <gnunet_namestore_service.h>
+#include <gnunet_credential_service.h>
+#include <gnunet_rest_lib.h>
+#include <gnunet_jsonapi_lib.h>
+#include <gnunet_jsonapi_util.h>
+#include <jansson.h>
+
+#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);
+}
+
+
+/**
+ * Task run on shutdown. Cleans up everything.
+ *
+ * @param cls unused
+ * @param tc scheduler context
+ */
+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 attr the attribute
+ * @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);
+ 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;
+}
+
+/**
+ * Function called with the result of a Credential lookup.
+ *
+ * @param cls the 'const char *' name that was resolved
+ * @param cd_count number of records returned
+ * @param cd array of @a cd_count records with the results
+ */
+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);
+}
+
+
+
+/**
+ * Function called with the result of a Credential lookup.
+ *
+ * @param cls the 'const char *' name that was resolved
+ * @param cd_count number of records returned
+ * @param cd array of @a cd_count records with the results
+ */
+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_free (entity_attr);
+ 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_free (entity_attr);
+ 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_free (entity_attr);
+ 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_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->subject_key)) {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Malformed subject key\n");
+ GNUNET_free (entity_attr);
+ 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");
+ 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");
+ 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 (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);
+}
+
+/**
+ * Handle rest request
+ *
+ * @param handle the lookup 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);
+}
+
+
+/**
+ * Function processing the REST call
+ *
+ * @param method HTTP method
+ * @param url URL of the HTTP request
+ * @param data body of the HTTP request (optional)
+ * @param data_size length of the body
+ * @param proc callback function for the result
+ * @param proc_cls closure for callback function
+ * @return GNUNET_OK if request accepted
+ */
+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 */
--- /dev/null
+#!/bin/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) PKEY1.user -> PKEY2.resu.user
+# (2) PKEY2.resu -> PKEY3
+# (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && 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
+
--- /dev/null
+#!/bin/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 && 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
+ echo -e "${RES_CRED}"
+ exit 0
+else
+ echo "FAIL: Failed to verify credential $RES_CRED."
+ exit 1
+fi
--- /dev/null
+@INLINE@ ../../contrib/no_forcestart.conf
+
+[PATHS]
+GNUNET_TEST_HOME = /tmp/test-gnunet-credential-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
+
--- /dev/null
+#!/bin/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) PKEY1.user -> PKEY2.resu.user
+# (2) PKEY2.resu -> PKEY3
+# (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+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`
+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
--- /dev/null
+#!/bin/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) PKEY1.user -> PKEY2.resu.user
+# (2) PKEY2.resu -> PKEY3
+# (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && 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
--- /dev/null
+@INLINE@ test_credential_defaults.conf
+
+[PATHS]
+GNUNET_TEST_HOME = /tmp/test-gnunet-credential-peer-1/
+
+[dht]
+AUTOSTART = YES
+
+[transport]
+PLUGINS =
+
+[credential]
+AUTOSTART = YES
+PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/credlog
+
+[rest]
+PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog
+
+[gns]
+#PREFIX = valgrind --leak-check=full --track-origins=yes
+AUTOSTART = 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
+
--- /dev/null
+#!/bin/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 && 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
+
+CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, -s`
+
+echo gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=\'$CREDS\' -c test_credential_lookup.conf
+#TODO2 Add -z swich like in gnunet-gns
+gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential="$CREDS" -c test_credential_lookup.conf
+
+
+#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
+ echo -e "${RES_CRED}"
+ exit 0
+else
+ echo "FAIL: Failed to verify credential $RES_CRED."
+ exit 1
+fi
--- /dev/null
+#!/bin/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 && 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,$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
+
+# (5) GNUnet issues Alice the credential "developer"
+CRED1=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
+# (5) GNUnet issues Alice the credential "user"
+CRED2=`$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 "$CRED1" -e 5m -c test_credential_lookup.conf
+gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED2" -e 5m -c test_credential_lookup.conf
+
+CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, -s`
+
+#TODO2 Add -z swich like in gnunet-gns
+RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential="$CREDS" -c test_credential_lookup.conf`
+
+
+#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
+ echo -e "${RES_CRED}"
+ exit 0
+else
+ echo "FAIL: Failed to verify credential $RES_CRED."
+ exit 1
+fi
--- /dev/null
+#!/bin/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 && 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
+ echo -e "${RES_CRED}"
+ exit 0
+else
+ echo "FAIL: Failed to verify credential $RES_CRED."
+ exit 1
+fi
--- /dev/null
+#!/bin/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`
+
+# (3) Isser.user -> Subject
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+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
+
+TEST_ATTR="user"
+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}')
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
+
+TEST_CREDENTIAL="t1"
+gnunet-namestore -p -z testsubject -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=`$DO_TIMEOUT gnunet-credential --verify --issuer=$ISSUER_KEY --attribute="$TEST_ATTR" --subject=$SUBJECT_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
+RES_CRED=`gnunet-credential --verify --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --subject=$SUBJECT_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
+
+#TODO cleanup properly
+gnunet-namestore -z testsubject -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
+gnunet-identity -D testsubject -c test_credential_lookup.conf
+gnunet-arm -e -c test_credential_lookup.conf
+echo $RES_CRED
+#TODO3 proper test
+if [ "$RES_CRED" == "Successful." ]
+then
+ exit 0
+else
+ echo "FAIL: Failed to verify credential."
+ exit 1
+fi
if (GNUNET_YES !=
GNUNET_OS_check_helper_binary (binary,
GNUNET_YES,
- "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")) //no nat, ipv4 only
+ "gnunet-vpn - - - 169.1.3.7 255.255.255.0")) //no nat, ipv4 only
{
GNUNET_free (binary);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
return;
proc = lr->lookup_proc;
proc_cls = lr->proc_cls;
- GNUNET_CONTAINER_DLL_remove (handle->lookup_head,
- handle->lookup_tail,
- lr);
- GNUNET_free (lr);
+
GNUNET_assert (GNUNET_OK ==
GNUNET_GNSRECORD_records_deserialize (mlen,
(const char*) &lookup_msg[1],
proc (proc_cls,
rd_count,
rd);
+ GNUNET_CONTAINER_DLL_remove (handle->lookup_head,
+ handle->lookup_tail,
+ lr);
+ if (NULL != lr->env)
+ GNUNET_MQ_discard (lr->env);
+ GNUNET_free (lr);
}
GNUNET_free (ival);
return box_str;
}
- case GNUNET_GNSRECORD_TYPE_REVERSE:
- {
- struct GNUNET_GNSRECORD_ReverseRecord rev;
- char *rev_str;
- char *pkey_str;
-
- if (data_size < sizeof (struct GNUNET_GNSRECORD_ReverseRecord))
- return NULL; /* malformed */
-
- memcpy (&rev,
- data,
- sizeof (rev));
- cdata = data;
- pkey_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&rev.pkey);
-
- GNUNET_asprintf (&rev_str,
- "%s %s %"SCNu64,
- &cdata[sizeof (rev)],
- pkey_str,
- rev.expiration.abs_value_us);
- GNUNET_free (pkey_str);
- return rev_str;
-
- }
default:
return NULL;
}
GNUNET_free (bval);
return GNUNET_OK;
}
- case GNUNET_GNSRECORD_TYPE_REVERSE:
- {
- struct GNUNET_GNSRECORD_ReverseRecord *rev;
- char known_by[253 + 1];
- struct GNUNET_TIME_Absolute expiration;
-
- /* TODO: From crypto_ecc.c
- * Why is this not a constant???
- */
- size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
- if (enclen % 5 > 0)
- enclen += 5 - enclen % 5;
- enclen /= 5; /* 260/5 = 52 */
- char pkey_str[enclen + 1];
-
- if (3 != SSCANF (s,
- "%253s %52s %"SCNu64,
- known_by,
- pkey_str,
- &expiration.abs_value_us))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to parse REVERSE record string `%s'\n"),
- s);
- return GNUNET_SYSERR;
- }
- *data_size = sizeof (struct GNUNET_GNSRECORD_ReverseRecord) + strlen (known_by) + 1;
- *data = rev = GNUNET_malloc (*data_size);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_ecdsa_public_key_from_string (pkey_str,
- strlen (pkey_str),
- &rev->pkey))
- {
- GNUNET_free (rev);
- return GNUNET_SYSERR;
- }
- rev->expiration = expiration;
- GNUNET_memcpy (&rev[1],
- known_by,
- strlen (known_by));
- return GNUNET_OK;
- }
default:
return GNUNET_SYSERR;
}
{ "VPN", GNUNET_GNSRECORD_TYPE_VPN },
{ "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS },
{ "BOX", GNUNET_GNSRECORD_TYPE_BOX },
- { "REVERSE", GNUNET_GNSRECORD_TYPE_REVERSE },
{ NULL, UINT32_MAX }
};
$(top_builddir)/src/namestore/libgnunetnamestore.la \
$(top_builddir)/src/identity/libgnunetidentity.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(top_builddir)/src/credential/libgnunetcredential.la \
$(top_builddir)/src/gns/libgnunetgns.la \
$(GN_LIBINTL) \
-ljansson
#include "gnunet_identity_service.h"
#include "gnunet_gnsrecord_lib.h"
#include "gnunet_namestore_service.h"
+#include "gnunet_credential_service.h"
#include "gnunet_statistics_service.h"
#include "gnunet_gns_service.h"
#include "gnunet_signatures.h"
*/
static struct GNUNET_GNS_Handle *gns_handle;
+/**
+ * Credential handle
+ */
+static struct GNUNET_CREDENTIAL_Handle *credential_handle;
+
/**
* Namestore qe
*/
*/
static const struct GNUNET_CONFIGURATION_Handle *cfg;
+struct VerifiedAttributeEntry
+{
+ /**
+ * DLL
+ */
+ struct VerifiedAttributeEntry *prev;
+
+ /**
+ * DLL
+ */
+ struct VerifiedAttributeEntry *next;
+
+ /**
+ * Attribute Name
+ */
+ char* name;
+};
struct ExchangeHandle
{
*/
char *scopes;
+ /**
+ * DLL
+ */
+ struct VerifiedAttributeEntry *v_attr_head;
+
+ /**
+ * DLL
+ */
+ struct VerifiedAttributeEntry *v_attr_tail;
+
/**
* nonce
*/
*/
struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+ /**
+ * Cred request
+ */
+ struct GNUNET_CREDENTIAL_Request *credential_request;
+
/**
* Attribute map
*/
GNUNET_IDENTITY_disconnect (identity_handle);
if (NULL != gns_handle)
GNUNET_GNS_disconnect (gns_handle);
+ if (NULL != credential_handle)
+ GNUNET_CREDENTIAL_disconnect (credential_handle);
if (NULL != ns_it)
GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
if (NULL != ns_qe)
ticket_destroy (handle->ticket);
if (NULL != handle->label)
GNUNET_free (handle->label);
+ if (NULL != handle->ns_it)
+ GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
+ if (NULL != handle->credential_request)
+ GNUNET_CREDENTIAL_request_cancel (handle->credential_request);
GNUNET_free (handle);
}
GNUNET_free (token_metadata);
}
+/**
+ * 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);
+ 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_vattr_collection (void* cls,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_Delegation *dc,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cred)
+{
+ struct IssueHandle *handle = cls;
+ struct VerifiedAttributeEntry *vattr;
+ json_t *cred_json;
+ json_t *cred_array;
+ int i;
+ handle->credential_request = NULL;
+
+ if (NULL == cred)
+ {
+ GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
+ return;
+ }
+ cred_array = json_array();
+ for (i=0;i<c_count;i++)
+ {
+ cred_json = credential_to_json (cred);
+ if (NULL == cred_json)
+ continue;
+ json_array_append (cred_array, cred_json);
+ token_add_attr_json (handle->token,
+ handle->v_attr_head->name,
+ cred_array);
+ }
+ json_decref (cred_array);
+ vattr = handle->v_attr_head;
+
+ GNUNET_CONTAINER_DLL_remove (handle->v_attr_head,
+ handle->v_attr_tail,
+ vattr);
+ GNUNET_free (vattr->name);
+ GNUNET_free (vattr);
+
+ if (NULL == handle->v_attr_head)
+ {
+ GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
+ return;
+ }
+ handle->credential_request = GNUNET_CREDENTIAL_collect (credential_handle,
+ &handle->aud_key,
+ handle->v_attr_head->name,
+ &handle->iss_key,
+ &handle_vattr_collection,
+ handle);
+
+}
+
static void
attr_collect_error (void *cls)
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n");
handle->ns_it = NULL;
- GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
-}
-
+ if (NULL == handle->v_attr_head)
+ {
+ GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
+ return;
+ }
+ handle->credential_request = GNUNET_CREDENTIAL_collect (credential_handle,
+ &handle->aud_key,
+ handle->v_attr_head->name,
+ &handle->iss_key,
+ &handle_vattr_collection,
+ handle);
+}
/**
* Collect attributes for token
*/
}
-
-static void
-find_existing_token_error (void *cls)
-{
- struct IssueHandle *handle = cls;
- cleanup_issue_handle (handle);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error looking for existing token\n");
- GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
-}
-
-
-static void
-find_existing_token_finished (void *cls)
-{
- struct IssueHandle *handle = cls;
- uint64_t rnd_key;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- ">>> No existing token found\n");
- rnd_key =
- GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
- UINT64_MAX);
- GNUNET_STRINGS_base64_encode ((char*)&rnd_key,
- sizeof (uint64_t),
- &handle->label);
- handle->ns_it = NULL;
- handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
- &handle->iss_key,
- &attr_collect_error,
- handle,
- &attr_collect,
- handle,
- &attr_collect_finished,
- handle);
-}
-
-
-/**
- *
- * Look for existing token
- *
- * @param cls the identity entry
- * @param zone the identity
- * @param lbl the name of the record
- * @param rd_count number of records
- * @param rd record data
- *
- */
-static void
-find_existing_token (void *cls,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
- const char *lbl,
- unsigned int rd_count,
- const struct GNUNET_GNSRECORD_Data *rd)
-{
- struct IssueHandle *handle = cls;
- const struct GNUNET_GNSRECORD_Data *token_metadata_record;
- struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
- struct GNUNET_HashCode key;
- int scope_count_token;
- char *scope;
- char *tmp_scopes;
-
- //There should be only a single record for a token under a label
- if (2 != rd_count)
- {
- GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
- return;
- }
-
- if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
- {
- token_metadata_record = &rd[0];
- }
- else
- {
- token_metadata_record = &rd[1];
- }
- if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
- {
- GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
- return;
- }
- ecdhe_privkey = *((struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data);
- aud_key =
- (struct GNUNET_CRYPTO_EcdsaPublicKey *)(token_metadata_record->data+sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey));
- tmp_scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
- if (0 != memcmp (aud_key, &handle->aud_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
- {
- char *tmp2 = GNUNET_STRINGS_data_to_string_alloc (aud_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
- //Audience does not match!
- char *tmp = GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA,
- token_metadata_record->data,
- token_metadata_record->data_size);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Token does not match audience %s vs %s. Moving on\n",
- tmp2,
- tmp);
- GNUNET_free (tmp_scopes);
- GNUNET_free (tmp2);
- GNUNET_free (tmp);
- GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
- return;
- }
-
- scope = strtok (tmp_scopes, ",");
- scope_count_token = 0;
- while (NULL != scope)
- {
- GNUNET_CRYPTO_hash (scope,
- strlen (scope),
- &key);
-
- if ((NULL != handle->attr_map) &&
- (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map, &key)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Issued token does not include `%s'. Moving on\n", scope);
- GNUNET_free (tmp_scopes);
- GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
- return;
- }
- scope_count_token++;
- scope = strtok (NULL, ",");
- }
- GNUNET_free (tmp_scopes);
- //All scopes in token are also in request. Now
- //Check length
- if ((NULL != handle->attr_map) &&
- (GNUNET_CONTAINER_multihashmap_size (handle->attr_map) == scope_count_token))
- {
- //We have an existing token
- handle->label = GNUNET_strdup (lbl);
- handle->ns_it = NULL;
- handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
- &handle->iss_key,
- &attr_collect_error,
- handle,
- &attr_collect,
- handle,
- &attr_collect_finished,
- handle);
-
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Nuber of attributes in token do not match request\n");
- //No luck
- GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
-}
-
/**
* Checks an issue message
*
const char *scopes;
char *scopes_tmp;
char *scope;
+ const char *v_attrs;
+ uint64_t rnd_key;
struct GNUNET_HashCode key;
struct IssueHandle *issue_handle;
+ struct VerifiedAttributeEntry *vattr_entry;
struct GNUNET_SERVICE_Client *client = cls;
scopes = (const char *) &im[1];
+ v_attrs = (const char *) &im[1] + ntohl(im->scope_len);
issue_handle = GNUNET_malloc (sizeof (struct IssueHandle));
issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
GNUNET_NO);
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
}
GNUNET_free (scopes_tmp);
+ scopes_tmp = GNUNET_strdup (v_attrs);
+
+ for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ","))
+ {
+ vattr_entry = GNUNET_new (struct VerifiedAttributeEntry);
+ vattr_entry->name = GNUNET_strdup (scope);
+ GNUNET_CONTAINER_DLL_insert (issue_handle->v_attr_head,
+ issue_handle->v_attr_tail,
+ vattr_entry);
+ }
+ GNUNET_free (scopes_tmp);
+
+
+
issue_handle->r_id = im->id;
issue_handle->aud_key = im->aud_key;
issue_handle->iss_key = im->iss_key;
issue_handle->scopes = GNUNET_strdup (scopes);
issue_handle->token = token_create (&issue_handle->iss_pkey,
&issue_handle->aud_key);
+ rnd_key =
+ GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
+ UINT64_MAX);
+ GNUNET_STRINGS_base64_encode ((char*)&rnd_key,
+ sizeof (uint64_t),
+ &issue_handle->label);
issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
- &im->iss_key,
- &find_existing_token_error,
+ &issue_handle->iss_key,
+ &attr_collect_error,
issue_handle,
- &find_existing_token,
+ &attr_collect,
issue_handle,
- &find_existing_token_finished,
+ &attr_collect_finished,
issue_handle);
}
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
}
-
+ credential_handle = GNUNET_CREDENTIAL_connect (cfg);
+ if (NULL == credential_handle)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
+ }
identity_handle = GNUNET_IDENTITY_connect (cfg,
&list_ego,
NULL);
*/
uint64_t nonce;
+ /**
+ * Length of scopes
+ */
+ uint64_t scope_len;
+
/**
* Expiration of token in NBO.
*/
const struct ExchangeResultMessage *erm)
{
char *str;
- size_t size = ntohs (erm->header.size) - sizeof (*erm);
+ size_t size = ntohs (erm->header.size);
- str = (char *) &erm[1];
+ str = (char *) &erm[0];
if ( (size > sizeof (struct ExchangeResultMessage)) &&
- ('\0' != str[size - sizeof (struct ExchangeResultMessage) - 1]) )
+ ('\0' != str[size - 1]) )
{
GNUNET_break (0);
return GNUNET_SYSERR;
const struct IssueResultMessage *irm)
{
char *str;
- size_t size = ntohs (irm->header.size) - sizeof (*irm);
- str = (char*) &irm[1];
+ size_t size = ntohs (irm->header.size);
+ str = (char*) &irm[0];
if ( (size > sizeof (struct IssueResultMessage)) &&
- ('\0' != str[size - sizeof (struct IssueResultMessage) - 1]) )
+ ('\0' != str[size - 1]) )
{
GNUNET_break (0);
return GNUNET_SYSERR;
const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key,
const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
const char* scopes,
+ const char* vattr,
struct GNUNET_TIME_Absolute expiration,
uint64_t nonce,
GNUNET_IDENTITY_PROVIDER_IssueCallback cb,
size_t slen;
slen = strlen (scopes) + 1;
+ if (NULL != vattr)
+ slen += strlen (vattr) + 1;
if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct IssueMessage))
{
GNUNET_break (0);
im->id = op->r_id;
im->iss_key = *iss_key;
im->aud_key = *aud_key;
+ im->scope_len = htonl (strlen(scopes)+1);
im->nonce = htonl (nonce);
im->expiration = GNUNET_TIME_absolute_hton (expiration);
- GNUNET_memcpy (&im[1], scopes, slen);
+ GNUNET_memcpy (&im[1], scopes, strlen(scopes));
+ if (NULL != vattr)
+ GNUNET_memcpy ((char*)&im[1]+strlen(scopes)+1, vattr, strlen(vattr));
GNUNET_CONTAINER_DLL_insert_tail (id->op_head,
id->op_tail,
op);
GNUNET_free (token);
}
+void
+token_add_attr_json (struct IdentityToken *token,
+ const char* key,
+ json_t* value)
+{
+ struct TokenAttr *attr;
+ struct TokenAttrValue *new_val;
+ GNUNET_assert (NULL != token);
+
+ new_val = GNUNET_malloc (sizeof (struct TokenAttrValue));
+ new_val->json_value = value;
+ json_incref(value);
+ for (attr = token->attr_head; NULL != attr; attr = attr->next)
+ {
+ if (0 == strcmp (key, attr->name))
+ break;
+ }
+
+ if (NULL == attr)
+ {
+ attr = GNUNET_malloc (sizeof (struct TokenAttr));
+ attr->name = GNUNET_strdup (key);
+ GNUNET_CONTAINER_DLL_insert (token->attr_head,
+ token->attr_tail,
+ attr);
+ }
+
+ GNUNET_CONTAINER_DLL_insert (attr->val_head,
+ attr->val_tail,
+ new_val);
+}
+
void
token_add_attr (struct IdentityToken *token,
const char* key,
if (json_is_integer (arr_value))
token_add_attr_int (token, key,
json_integer_value (arr_value));
- else
+ else if (json_is_string (arr_value))
token_add_attr (token,
key,
json_string_value (arr_value));
+ else
+ token_add_attr_json (token,
+ key,
+ (json_t*)arr_value);
}
} else {
if (json_is_integer (value))
token_add_attr_int (token, key,
json_integer_value (value));
- else
+ else if (json_is_string (value))
token_add_attr (token, key, json_string_value (value));
+ else
+ token_add_attr_json (token, key, (json_t*)value);
}
}
GNUNET_asprintf (&tmp_buf, "%s", raw_data);
ecdh_pubkey_str = strtok (tmp_buf, ",");
enc_token_str = strtok (NULL, ",");
-
+
GNUNET_assert (NULL != ecdh_pubkey_str);
GNUNET_assert (NULL != enc_token_str);
json_object_set_new (root,
attr->name,
json_string (val->value));
- } else {
+ } else if (NULL != val->json_value) {
+ json_object_set (root,
+ attr->name,
+ val->json_value);
+ }else {
json_object_set_new (root,
attr->name,
json_integer (val->int_value));
purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
write_ptr = (char*) &purpose[1];
GNUNET_memcpy (write_ptr,
- &ticket->ecdh_pubkey,
- sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+ &ticket->ecdh_pubkey,
+ sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
GNUNET_memcpy (write_ptr, enc_ticket_payload, strlen (code_payload_str));
GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign (priv_key,
nonce_str = json_string_value (nonce_json);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found nonce: %s\n", nonce_str);
-
+
GNUNET_assert (0 != sscanf (nonce_str, "%"SCNu64, &nonce));
*result = ticket_payload_create (nonce,
* used if NULL == value
*/
uint64_t int_value;
+
+ /**
+ * Json value
+ */
+ json_t *json_value;
};
struct TokenTicketPayload
* @param value the value
*
*/
- void
- token_add_json (const struct IdentityToken *token,
- const char* key,
- json_t* value);
+void
+token_add_attr_json (struct IdentityToken *token,
+ const char* key,
+ json_t* value);
/**
* Serialize a token. The token will be signed and base64 according to the
*
* @return GNUNET_OK on success
*/
- int
- token_serialize (const struct IdentityToken*token,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- struct GNUNET_CRYPTO_EcdhePrivateKey **ecdhe_privkey,
- char **result);
+int
+token_serialize (const struct IdentityToken*token,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+ struct GNUNET_CRYPTO_EcdhePrivateKey **ecdhe_privkey,
+ char **result);
/**
* Parses the serialized token and returns a token
*
* @return GNUNET_OK on success
*/
- int
- token_parse (const char* data,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- struct IdentityToken **result);
+int
+token_parse (const char* data,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+ struct IdentityToken **result);
/**
* Parses the serialized token and returns a token
*
* @return GNUNET_OK on success
*/
- int
- token_to_string (const struct IdentityToken *token,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- char **result);
+int
+token_to_string (const struct IdentityToken *token,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+ char **result);
/**
*
*
* @return GNUNET_OK on success
*/
- int
- ticket_serialize (struct TokenTicket *ticket,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- char **result);
+int
+ticket_serialize (struct TokenTicket *ticket,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+ char **result);
/**
* Destroys a ticket
*/
#define GNUNET_IDENTITY_TOKEN_ATTR_LIST "requested_attrs"
+/**
+ * Attributes passed to issue request
+ */
+#define GNUNET_IDENTITY_TOKEN_V_ATTR_LIST "requested_verified_attrs"
+
+
/**
* Token expiration string
*/
char *ticket_str;
char *token_str;
char *result_str;
+
+ handle->idp_op = NULL;
if (NULL == ticket)
{
char *exp_str;
char *nonce_str;
char *scopes;
+ char *vattrs;
uint64_t time;
uint64_t nonce;
scopes = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
&key);
+ //vattrs
+ GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_V_ATTR_LIST,
+ strlen (GNUNET_IDENTITY_TOKEN_V_ATTR_LIST),
+ &key);
+
+ vattrs = NULL;
+ if ( GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+ &key) )
+ {
+ vattrs = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+ &key);
+ }
+
+
//Token audience
GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST,
&key) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Audience missing!\n");
+ "Audience missing!\n");
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
&key);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Audience to issue token for: %s\n",
- audience);
+ "Audience to issue token for: %s\n",
+ audience);
priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
&key);
GNUNET_assert (NULL != nonce_str);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Request nonce: %s\n",
- nonce_str);
+ "Request nonce: %s\n",
+ nonce_str);
GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &nonce));
//Get expiration for token from URL parameter
priv_key,
&aud_key,
scopes,
+ vattrs,
exp_time,
nonce,
&token_creat_cont,
rd[i].data_size);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token: %s\n", data);
json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
- label);
+ label);
issuer = json_string (handle->ego_head->identifier);
GNUNET_JSONAPI_resource_add_attr (json_resource,
- GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
- issuer);
+ GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
+ issuer);
json_decref (issuer);
token = json_string (data);
GNUNET_JSONAPI_resource_add_attr (json_resource,
- GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
- token);
+ GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
+ token);
json_decref (token);
GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
return;
}
nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
- &key);
+ &key);
GNUNET_assert (NULL != nonce_str);
GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &expected_nonce));
continue;
json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO,
ego_entry->keystring);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Egoname: %s\n",
- ego_entry->identifier);
name_str = json_string (ego_entry->identifier);
GNUNET_JSONAPI_resource_add_attr (
json_resource,
/**
* @author Martin Schanzenbach
+ * @author Adnan Husain
*
* @file
* API to the Credential service
#include "gnunet_util_lib.h"
#include "gnunet_gns_service.h"
+#include "gnunet_identity_service.h"
#ifdef __cplusplus
extern "C"
/**
* Handle to control a lookup operation.
*/
-struct GNUNET_CREDENTIAL_LookupRequest;
+struct GNUNET_CREDENTIAL_Request;
+
+/*
+* Enum used for checking whether the issuer has the authority to issue credentials or is just a subject
+*/
+enum GNUNET_CREDENTIAL_CredentialFlags {
+
+ //Subject had credentials before, but have been revoked now
+ GNUNET_CREDENTIAL_FLAG_REVOKED=0,
+
+ //Subject flag indicates that the subject is a holder of this credential and may present it as such
+ GNUNET_CREDENTIAL_FLAG_SUBJECT=1,
+
+ //Issuer flag is used to signify that the subject is allowed to issue this credential and delegate issuance
+ GNUNET_CREDENTIAL_FLAG_ISSUER=2
+
+};
+
+GNUNET_NETWORK_STRUCT_BEGIN
+/**
+ * The attribute delegation record
+ */
+struct GNUNET_CREDENTIAL_DelegationRecord {
+
+ /**
+ * Number of delegation sets in this record
+ */
+ uint32_t set_count;
+
+ /**
+ * Length of delegation sets
+ */
+ uint64_t data_size;
+ /**
+ * Followed by set_count DelegationSetRecords
+ *
+ */
+};
+
+/**
+ * The attribute delegation record
+ */
+struct GNUNET_CREDENTIAL_DelegationRecordSet {
+
+ /**
+ * Public key of the subject this attribute was delegated to
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * Length of attribute, may be 0
+ */
+ uint32_t subject_attribute_len;
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+/**
+ * The attribute delegation record
+ */
+struct GNUNET_CREDENTIAL_DelegationSet {
+
+ /**
+ * Public key of the subject this attribute was delegated to
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ uint32_t subject_attribute_len;
+
+ /**
+ * The subject attribute
+ */
+ const char *subject_attribute;
+};
+
+
+/**
+ * A delegation
+ */
+struct GNUNET_CREDENTIAL_Delegation {
+
+ /**
+ * The issuer of the delegation
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * Public key of the subject this attribute was delegated to
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * Length of the attribute
+ */
+ uint32_t issuer_attribute_len;
+
+ /**
+ * The attribute
+ */
+ const char *issuer_attribute;
+
+ /**
+ * Length of the attribute
+ */
+ uint32_t subject_attribute_len;
+
+ /**
+ * The attribute
+ */
+ const char *subject_attribute;
+};
+
+
+/**
+ * A credential
+ */
+struct GNUNET_CREDENTIAL_Credential {
+
+ /**
+ * The issuer of the credential
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * Public key of the subject this credential was issued to
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * Signature of this credential
+ */
+ struct GNUNET_CRYPTO_EcdsaSignature signature;
+
+ /**
+ * Expiration of this credential
+ */
+ struct GNUNET_TIME_Absolute expiration;
+
+ /**
+ * Length of the attribute
+ */
+ uint32_t issuer_attribute_len;
+
+ /**
+ * The attribute
+ */
+ const char *issuer_attribute;
+
+};
+
/**
* @param cfg configuration to use
* @return handle to the Credential service, or NULL on error
*/
-struct GNUNET_Credential_Handle *
+struct GNUNET_CREDENTIAL_Handle *
GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
/**
- * Iterator called on obtained result for a Credential lookup.
+ * Iterator called on obtained result for an attribute verification.
*
* @param cls closure
- * @param issuer the issuer chain
- * @param issuer_len length of issuer chain
- * @param value the value returned
+ * @param d_count the number of delegations processed
+ * @param delegation_chain the delegations processed
+ * @param c_count the number of credentials found
+ * @param credential the credentials
*/
-typedef void
-(*GNUNET_CREDENTIAL_LookupResultProcessor) (void *cls,
- struct GNUNET_IDENTITY_Ego *issuer,
- uint16_t issuer_len,
- const struct GNUNET_CREDENTIAL_Value *value);
+typedef void (*GNUNET_CREDENTIAL_CredentialResultProcessor) (void *cls,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *credential);
+/**
+ * Iterator called on obtained result for an attribute delegation.
+ *
+ * @param cls closure
+ * @param success GNUNET_YES if successful
+ * @param result the record data that can be handed to the subject
+ */
+typedef void (*GNUNET_CREDENTIAL_DelegateResultProcessor) (void *cls,
+ uint32_t success);
/**
- * Perform an asynchronous lookup operation for a credential.
+ * Iterator called on obtained result for an attribute delegation removal.
+ *
+ * @param cls closure
+ * @param success GNUNET_YES if successful
+ * @param result the record data that can be handed to the subject
+ */
+typedef void (*GNUNET_CREDENTIAL_RemoveDelegateResultProcessor) (void *cls,
+ uint32_t success);
+
+
+/**
+ * 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 credential the credential to look up
- * @param subject Ego to check the credential for
+ * @param issuer_key the issuer public key
+ * @param issuer_attribute the issuer attribute
+ * @param subject_key the subject public key
+ * @param subject_attribute the attribute claimed by the subject
* @param proc function to call on result
* @param proc_cls closure for processor
* @return handle to the queued request
*/
-struct GNUNET_CREDENTIAL_LookupRequest *
-GNUNET_CREDENTIAL_lookup (struct GNUNET_CREDENTIAL_Handle *handle,
- const char *credential,
- const struct GNUNET_IDENTITY_Ego *subject,
- GNUNET_CREDENTIAL_LookupResultProcessor proc,
+struct GNUNET_CREDENTIAL_Request*
+GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
+ const char *issuer_attribute,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
+ uint32_t credential_count,
+ const struct GNUNET_CREDENTIAL_Credential *credentials,
+ GNUNET_CREDENTIAL_CredentialResultProcessor proc,
void *proc_cls);
+struct GNUNET_CREDENTIAL_Request*
+GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
+ const char *issuer_attribute,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key,
+ GNUNET_CREDENTIAL_CredentialResultProcessor proc,
+ void *proc_cls);
/**
- * Issue a credential to an identity
+ * Delegate an attribute
*
* @param handle handle to the Credential service
- * @param issuer the identity that issues the credential
- * @param subject the subject of the credential
- * @param credential the name of the credential
- * @param value the value of the credential
+ * @param issuer the ego that should be used to delegate the attribute
+ * @param attribute the name of the attribute to delegate
+ * @param subject the subject of the delegation
+ * @param delegated_attribute the name of the attribute that is delegated to
+ * @return handle to the queued request
+ */
+struct GNUNET_CREDENTIAL_Request *
+GNUNET_CREDENTIAL_add_delegation (struct GNUNET_CREDENTIAL_Handle *handle,
+ struct GNUNET_IDENTITY_Ego *issuer,
+ const char *attribute,
+ struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
+ const char *delegated_attribute,
+ GNUNET_CREDENTIAL_DelegateResultProcessor proc,
+ void *proc_cls);
+
+/**
+ * Remove a delegation
+ *
+ * @param handle handle to the Credential service
+ * @param issuer the ego that was used to delegate the attribute
+ * @param attribute the name of the attribute that is delegated
* @return handle to the queued request
*/
-struct GNUNET_CREDENTIAL_IssueRequest *
-GNUNET_CREDENTIAL_issue (struct GNUNET_CREDENTIAL_Handle *handle,
- struct GNUNET_IDENTITY_Ego *issuer,
- struct GNUNET_IDENTITY_Ego *subject,
- const char *credential,
- struct GNUNET_CREDENTIAL_Value *value,
- GNUNET_CREDENTIAL_IssueResultProcessor proc,
- void *proc_cls);
+struct GNUNET_CREDENTIAL_Request *
+GNUNET_CREDENTIAL_remove_delegation (struct GNUNET_CREDENTIAL_Handle *handle,
+ struct GNUNET_IDENTITY_Ego *issuer,
+ const char *attribute,
+ GNUNET_CREDENTIAL_RemoveDelegateResultProcessor proc,
+ void *proc_cls);
+
+
+
+/**
+ * Issue an attribute to a subject
+ *
+ * @param handle handle to the Credential service
+ * @param issuer the ego that should be used to issue the attribute
+ * @param subject the subject of the attribute
+ * @param attribute the name of the attribute
+ * @param expiration the TTL of the credential
+ * @return handle to the queued request
+ */
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_issue (
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
+ struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
+ const char *attribute,
+ struct GNUNET_TIME_Absolute *expiration);
+
/**
* Remove a credential
* @param credential the name of the credential
* @return handle to the queued request
*/
-struct GNUNET_CREDENTIAL_IssueRequest *
-GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle *handle,
- struct GNUNET_IDENTITY_Ego *issuer,
- struct GNUNET_IDENTITY_Ego *subject,
- const char *credential,
- GNUNET_CREDENTIAL_IssueResultProcessor proc,
- void *proc_cls);
-
+/**
+ struct GNUNET_CREDENTIAL_IssueRequest *
+ GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle *handle,
+ struct GNUNET_IDENTITY_Ego *issuer,
+ struct GNUNET_IDENTITY_Ego *subject,
+ const char *credential,
+ GNUNET_CREDENTIAL_IssueResultProcessor proc,
+ void *proc_cls);
+ */
/**
* @param lr the lookup request to cancel
*/
void
-GNUNET_CREDENTIAL_lookup_cancel (struct GNUNET_CREDENTIAL_LookupRequest *lr);
+GNUNET_CREDENTIAL_request_cancel (struct GNUNET_CREDENTIAL_Request *vr);
#if 0 /* keep Emacsens' auto-indent happy */
*/
#define GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA 65546
+/**
+ * Record type for credential
+ */
+#define GNUNET_GNSRECORD_TYPE_CREDENTIAL 65547
+
+/**
+ * Record type for policies
+ */
+#define GNUNET_GNSRECORD_TYPE_POLICY 65548
+
/**
* Record type for reverse lookups
*/
-#define GNUNET_GNSRECORD_TYPE_REVERSE 65548
+#define GNUNET_GNSRECORD_TYPE_ATTRIBUTE 65549
+
/**
* Flags that can be set for a record.
const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key,
const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
const char* scope,
+ const char* vattr,
struct GNUNET_TIME_Absolute expiration,
uint64_t nonce,
GNUNET_IDENTITY_PROVIDER_IssueCallback cb,
#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT 964
+
+/**************************************************
+ *
+ * CREDENTIAL MESSAGE TYPES
+ */
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY 971
+
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT 972
+
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT 973
+
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT 974
+
/******************************************************************************/
*/
#define GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET 27
+/**
+ * Signature for a GNUnet credential
+ */
+#define GNUNET_SIGNATURE_PURPOSE_CREDENTIAL 28
+
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
GNUNET_JSONAPI_KEY_ERRORS,
res_json);
} else {
- switch (doc->res_count)
+ if (0 == doc->res_count)
{
- case 0:
- res_json = json_null();
- break;
- case 1:
+ res_json = json_null();
+ } else {
+ res_json = json_array ();
+ for (res = doc->res_list_head;
+ res != NULL;
+ res = res->next)
+ {
GNUNET_assert (GNUNET_OK ==
- GNUNET_JSONAPI_resource_to_json (doc->res_list_head,
- &res_json));
- break;
- default:
- res_json = json_array ();
- for (res = doc->res_list_head;
- res != NULL;
- res = res->next)
- {
- GNUNET_assert (GNUNET_OK ==
- GNUNET_JSONAPI_resource_to_json (res,
- &res_json_tmp));
- json_array_append (res_json, res_json_tmp);
- }
- break;
+ GNUNET_JSONAPI_resource_to_json (res,
+ &res_json_tmp));
+ json_array_append_new (res_json, res_json_tmp);
+ }
}
json_object_set_new (*root_json,
GNUNET_JSONAPI_KEY_DATA,
{
struct GNUNET_JSONAPI_Resource *res;
- if ( (NULL == type) || (0 == strlen (type)) )
+ if (NULL == type)
return NULL;
- if ( (NULL == id) || (0 == strlen (id)) )
+ if (NULL == id)
return NULL;
res = GNUNET_new (struct GNUNET_JSONAPI_Resource);
struct MHD_Response *resp;
handle->list_it = NULL;
+ if (NULL == handle->resp_object)
+ handle->resp_object = GNUNET_JSONAPI_document_new ();
+
if (GNUNET_SYSERR ==
GNUNET_JSONAPI_document_serialize (handle->resp_object,
&result))
{
- do_error (handle);
+ handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ GNUNET_SCHEDULER_add_now (&do_error,
+ handle);
return;
}
resp = GNUNET_REST_create_response (result);
if (0 < json_array_size(result_array))
{
json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO,
- rname);
+ rname);
GNUNET_JSONAPI_resource_add_attr (json_resource,
- GNUNET_REST_JSONAPI_NAMESTORE_RECORD,
- result_array);
+ GNUNET_REST_JSONAPI_NAMESTORE_RECORD,
+ result_array);
GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
}
}
term_data[handle->rest_handle->data_size] = '\0';
GNUNET_memcpy (term_data,
- handle->rest_handle->data,
- handle->rest_handle->data_size);
+ handle->rest_handle->data,
+ handle->rest_handle->data_size);
data_js = json_loads (term_data,
JSON_DECODE_ANY,
&err);
if ((NULL == handle->zkey_str) ||
(GNUNET_OK !=
GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->zkey_str,
- strlen (handle->zkey_str),
+ strlen (handle->zkey_str),
&pubkey)))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
if (GNUNET_OK !=
GNUNET_JSONAPI_handle_request (handle->rest_handle,
- handlers,
- &err,
- handle))
+ handlers,
+ &err,
+ handle))
{
handle->response_code = err.error_code;
GNUNET_SCHEDULER_add_now (&do_error,
- (void *) handle);
+ (void *) handle);
}
}