aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--src/Makefile.am1
-rw-r--r--src/credential/Makefile.am113
-rw-r--r--src/credential/credential.conf.in5
-rw-r--r--src/credential/credential.h91
-rw-r--r--src/credential/credential_api.c410
-rw-r--r--src/credential/gnunet-credential.c382
-rw-r--r--src/credential/gnunet-service-credential.c425
-rw-r--r--src/credential/plugin_gnsrecord_credential.c257
-rwxr-xr-xsrc/credential/test_credential_lookup.sh40
-rw-r--r--src/include/gnunet_credential_service.h60
-rw-r--r--src/include/gnunet_gnsrecord_lib.h7
-rw-r--r--src/include/gnunet_protocols.h9
13 files changed, 1794 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac
index d839f8b4e6..1a24513929 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1581,6 +1581,8 @@ src/gnsrecord/Makefile
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
diff --git a/src/Makefile.am b/src/Makefile.am
index 98ca70ae32..2877cab0b8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -109,6 +109,7 @@ SUBDIRS = \
revocation \
vpn \
gns \
+ credential \
$(CONVERSATION_DIR) \
fs \
exit \
diff --git a/src/credential/Makefile.am b/src/credential/Makefile.am
new file mode 100644
index 0000000000..6469895e37
--- /dev/null
+++ b/src/credential/Makefile.am
@@ -0,0 +1,113 @@
+# 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
+# test_gns_nick_shorten.conf \
+#### test_gns_proxy.conf \
+# test_gns_simple_lookup.conf \
+# gns-helper-service-w32.conf \
+# w32nsp.def \
+# gnunet-gns-proxy-setup-ca \
+# zonefiles/J7POEUT41A8PBFS7KVVDRF88GBOU4HK8PSU5QKVLVE3R9T91E99G.zkey \
+# zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey \
+# zonefiles/test_zonekey \
+# $(check_SCRIPTS)
+
+
+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_gns.la
+#endif
+#endif
+
+
+gnunet_credential_SOURCES = \
+ gnunet-credential.c
+gnunet_credential_LDADD = \
+ libgnunetcredential.la \
+ $(top_builddir)/src/util/libgnunetutil.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 = \
+ $(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 = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(GN_LIBINTL)
+
+
+libgnunetcredential_la_SOURCES = \
+ credential_api.c credential.h
+libgnunetcredential_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
+libgnunetcredential_la_LDFLAGS = \
+ $(GN_LIB_LDFLAGS)
+
+
+#libgnunet_plugin_rest_gns_la_SOURCES = \
+# plugin_rest_gns.c
+#libgnunet_plugin_rest_gns_la_LIBADD = \
+# libgnunetgns.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_gns_la_LDFLAGS = \
+# $(GN_PLUGIN_LDFLAGS)
+
+
+#check_SCRIPTS = \
+ #test_gns_lookup.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
diff --git a/src/credential/credential.conf.in b/src/credential/credential.conf.in
new file mode 100644
index 0000000000..71f3066ca9
--- /dev/null
+++ b/src/credential/credential.conf.in
@@ -0,0 +1,5 @@
+[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
diff --git a/src/credential/credential.h b/src/credential/credential.h
new file mode 100644
index 0000000000..597c34a3d7
--- /dev/null
+++ b/src/credential/credential.h
@@ -0,0 +1,91 @@
+/*
+ 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 lookup credentials.
+ */
+struct LookupMessage
+{
+ /**
+ * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Subject public key
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * Trust anchor
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /* Followed by the zero-terminated credential to look up */
+
+};
+
+
+/**
+ * Message from CREDENTIAL service to client: new results.
+ */
+struct LookupResultMessage
+{
+ /**
+ * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP_RESULT
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+
+ /**
+ * The number of credentials in the response
+ */
+ uint32_t cd_count GNUNET_PACKED;
+
+ /* followed by cd_count GNUNET_CREDENTIAL_RecordData structs*/
+
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
+
diff --git a/src/credential/credential_api.c b/src/credential/credential_api.c
new file mode 100644
index 0000000000..1efe2d0892
--- /dev/null
+++ b/src/credential/credential_api.c
@@ -0,0 +1,410 @@
+/*
+ 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 "credential.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 lookup request
+ */
+struct GNUNET_CREDENTIAL_LookupRequest
+{
+
+ /**
+ * DLL
+ */
+ struct GNUNET_CREDENTIAL_LookupRequest *next;
+
+ /**
+ * DLL
+ */
+ struct GNUNET_CREDENTIAL_LookupRequest *prev;
+
+ /**
+ * handle to credential service
+ */
+ struct GNUNET_CREDENTIAL_Handle *credential_handle;
+
+ /**
+ * processor to call on lookup result
+ */
+ GNUNET_CREDENTIAL_LookupResultProcessor lookup_proc;
+
+ /**
+ * @e lookup_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 lookup requests.
+ */
+ struct GNUNET_CREDENTIAL_LookupRequest *lookup_head;
+
+ /**
+ * Tail of linked list of active lookup requests.
+ */
+ struct GNUNET_CREDENTIAL_LookupRequest *lookup_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 LookupResultMessage *lookup_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 LookupResultMessage *lookup_msg)
+{
+ struct GNUNET_CREDENTIAL_Handle *handle = cls;
+ uint32_t cd_count = ntohl (lookup_msg->cd_count);
+ struct GNUNET_CREDENTIAL_RecordData cd[cd_count];
+ uint32_t r_id = ntohl (lookup_msg->id);
+ struct GNUNET_CREDENTIAL_LookupRequest *lr;
+ GNUNET_CREDENTIAL_LookupResultProcessor proc;
+ void *proc_cls;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Received lookup reply from CREDENTIAL service (%u credentials)\n",
+ (unsigned int) cd_count);
+ for (lr = handle->lookup_head; NULL != lr; lr = lr->next)
+ if (lr->r_id == r_id)
+ break;
+ if (NULL == lr)
+ 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_CREDENTIAL_records_deserialize (mlen,
+ (const char*) &lookup_msg[1],
+ rd_count,
+ rd));
+ */
+ proc (proc_cls,
+ NULL,
+ cd_count,
+ cd); // TODO
+}
+
+
+/**
+ * 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_LOOKUP_RESULT,
+ struct LookupResultMessage,
+ NULL),
+ GNUNET_MQ_handler_end ()
+ };
+ struct GNUNET_CREDENTIAL_LookupRequest *lh;
+
+ 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 (lh = handle->lookup_head; NULL != lh; lh = lh->next)
+ GNUNET_MQ_send_copy (handle->mq,
+ lh->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->lookup_head);
+ GNUNET_free (handle);
+}
+
+
+/**
+ * Cancel pending lookup request
+ *
+ * @param lr the lookup request to cancel
+ */
+void
+GNUNET_CREDENTIAL_lookup_cancel (struct GNUNET_CREDENTIAL_LookupRequest *lr)
+{
+ struct GNUNET_CREDENTIAL_Handle *handle = lr->credential_handle;
+
+ GNUNET_CONTAINER_DLL_remove (handle->lookup_head,
+ handle->lookup_tail,
+ lr);
+ GNUNET_MQ_discard (lr->env);
+ GNUNET_free (lr);
+}
+
+
+/**
+ * Perform an asynchronous lookup operation for a credential.
+ *
+ * @param handle handle to the Credential service
+ * @param credential the credential to look up
+ * @param subject Ego to check the credential for
+ * @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,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
+ uint32_t credential_flags,
+ uint32_t max_delegation_depth,
+ GNUNET_CREDENTIAL_LookupResultProcessor proc,
+ void *proc_cls)
+{
+ /* IPC to shorten credential names, return shorten_handle */
+ struct LookupMessage *lookup_msg;
+ struct GNUNET_CREDENTIAL_LookupRequest *lr;
+ size_t nlen;
+
+ if (NULL == credential)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ //DEBUG LOG
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to lookup `%s' in CREDENTIAL\n",
+ credential);
+ nlen = strlen (credential) + 1;
+ if (nlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*lr))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ lr = GNUNET_new (struct GNUNET_CREDENTIAL_LookupRequest);
+ lr->credential_handle = handle;
+ lr->lookup_proc = proc;
+ lr->proc_cls = proc_cls;
+ lr->r_id = handle->r_id_gen++;
+ lr->env = GNUNET_MQ_msg_extra (lookup_msg,
+ nlen,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP);
+ lookup_msg->id = htonl (lr->r_id);
+ lookup_msg->subject_key = *subject_key;
+ lookup_msg->issuer_key = *issuer_key;
+ GNUNET_memcpy (&lookup_msg[1],
+ credential,
+ nlen);
+ GNUNET_CONTAINER_DLL_insert (handle->lookup_head,
+ handle->lookup_tail,
+ lr);
+ if (NULL != handle->mq)
+ GNUNET_MQ_send_copy (handle->mq,
+ lr->env);
+ return lr;
+}
+
+
+/* end of credential_api.c */
diff --git a/src/credential/gnunet-credential.c b/src/credential/gnunet-credential.c
new file mode 100644
index 0000000000..363ed03fce
--- /dev/null
+++ b/src/credential/gnunet-credential.c
@@ -0,0 +1,382 @@
+/*
+ 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_identity_service.h>
+#include <gnunet_credential_service.h>
+
+/**
+ * Configuration we are using.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * 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;
+
+/**
+ * Credential to lookup. (-u option)
+ */
+static char *lookup_credential;
+
+/**
+ * Handle to lookup request
+ */
+static struct GNUNET_CREDENTIAL_LookupRequest *lookup_request;
+
+/**
+ * Lookup an ego with the identity service.
+ */
+static struct GNUNET_IDENTITY_EgoLookup *el;
+
+/**
+ * Handle for identity service.
+ */
+static struct GNUNET_IDENTITY_Handle *identity;
+
+/**
+ * Active operation on identity service.
+ */
+static struct GNUNET_IDENTITY_Operation *id_op;
+
+/**
+ * Task scheduled to handle timeout.
+ */
+static struct GNUNET_SCHEDULER_Task *tt;
+
+/**
+ * Subject pubkey string
+ */
+static char *subject_key;
+
+/**
+ * Subject pubkey string
+ */
+static char *issuer_key;
+
+/*
+ * Credential flags
+ */
+static int credential_flags;
+
+/*
+ * Maximum delegation depth
+ */
+static int max_delegation_depth;
+
+
+
+/**
+ * Identity of the zone to use for the lookup (-z option)
+ */
+static char *zone_ego_name;
+
+
+/**
+ * Task run on shutdown. Cleans up everything.
+ *
+ * @param cls unused
+ */
+static void
+do_shutdown (void *cls)
+{
+ if (NULL != el)
+ {
+ GNUNET_IDENTITY_ego_lookup_cancel (el);
+ el = NULL;
+ }
+ if (NULL != id_op)
+ {
+ GNUNET_IDENTITY_cancel (id_op);
+ id_op = NULL;
+ }
+ if (NULL != lookup_request)
+ {
+ GNUNET_CREDENTIAL_lookup_cancel (lookup_request);
+ lookup_request = NULL;
+ }
+ if (NULL != identity)
+ {
+ GNUNET_IDENTITY_disconnect (identity);
+ identity = 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_lookup_result (void *cls,
+ struct GNUNET_IDENTITY_Ego *issuer,
+ uint16_t issuer_len,
+ const struct GNUNET_CREDENTIAL_RecordData *data)
+{
+
+
+ lookup_request = NULL;
+ if (0 == issuer_len)
+ printf ("No results.\n");
+ else
+ printf ("%u\n",
+ issuer_len);
+
+
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+
+
+
+/**
+ * Perform the actual resolution, with the subject pkey and
+ * the issuer public key
+ *
+ * @param pkey public key to use for the zone, can be NULL
+ * @param shorten_key private key used for shortening, can be NULL
+ */
+static void
+lookup_credentials (struct GNUNET_IDENTITY_Ego *ego)
+{
+
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_pkey;
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey;
+
+ if (NULL != subject_key && NULL != issuer_key && NULL != lookup_credential)
+ {
+ 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_OK !=
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
+ strlen (issuer_key),
+ &issuer_pkey))
+ {
+ fprintf (stderr,
+ _("Authority public key `%s' is not well-formed\n"),
+ issuer_key);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
+ lookup_request = GNUNET_CREDENTIAL_lookup(credential,
+ lookup_credential,
+ ego,
+ &subject_pkey,
+ &issuer_pkey,
+ credential_flags,
+ max_delegation_depth,
+ &handle_lookup_result,
+ NULL);
+ return;
+ }
+ else
+ {
+ fprintf (stderr,
+ _("Please specify name to lookup, subject key and issuer key!\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+}
+
+
+/**
+ * Method called to with the ego we are to use for the lookup,
+ * when the ego is the one for the default master zone.
+ *
+ * @param cls closure (NULL, unused)
+ * @param ego ego handle, NULL if not found
+ * @param ctx context for application to store data for this ego
+ * (during the lifetime of this process, initially NULL)
+ * @param name name assigned by the user for this ego,
+ * NULL if the user just deleted the ego and it
+ * must thus no longer be used
+ */
+static void
+identity_master_cb (void *cls,
+ struct GNUNET_IDENTITY_Ego *ego,
+ void **ctx,
+ const char *name)
+{
+
+ id_op = NULL;
+ if (NULL == ego)
+ {
+ fprintf (stderr,
+ _("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
+ lookup_credentials(ego);
+
+
+}
+
+
+/**
+ * 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;
+ credential = GNUNET_CREDENTIAL_connect (cfg);
+ identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
+
+
+
+
+ if (NULL == credential)
+ {
+ fprintf (stderr,
+ _("Failed to connect to CREDENTIAL\n"));
+ return;
+ }
+ if (NULL == identity)
+ {
+ fprintf (stderr,
+ _("Failed to connect to IDENTITY\n"));
+ return;
+ }
+ tt = GNUNET_SCHEDULER_add_delayed (timeout,
+ &do_timeout, NULL);
+ GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
+
+
+
+ GNUNET_break (NULL == id_op);
+ id_op = GNUNET_IDENTITY_get (identity,
+ "gns-master",//# TODO: Create credential-master
+ &identity_master_cb,
+ cls);
+ GNUNET_assert (NULL != id_op);
+
+
+
+
+}
+
+
+/**
+ * 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)
+{
+ static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+ {'u', "lookup", "CREDENTIAL",
+ gettext_noop ("Lookup a record for the given credential"), 1,
+ &GNUNET_GETOPT_set_string, &lookup_credential},
+ /** { 'T', "timeout", "DELAY",
+ gettext_noop ("Specify timeout for the lookup"), 1,
+ &GNUNET_GETOPT_set_relative_time, &timeout },
+ {'t', "type", "TYPE",
+ gettext_noop ("Specify the type of the record to lookup"), 1,
+ &GNUNET_GETOPT_set_string, &lookup_type},**/
+ {'z', "zone", "NAME",
+ gettext_noop ("Specify the name of the ego of the zone to lookup the record in"), 1,
+ &GNUNET_GETOPT_set_string, &zone_ego_name},
+ {'s', "subject", "PKEY",
+ gettext_noop ("Specify the public key of the subject to lookup the credential for"), 1,
+ &GNUNET_GETOPT_set_string, &subject_key},
+ {'i', "issuer", "PKEY",
+ gettext_noop ("Specify the public key of the authority to verify the credential against"), 1,
+ &GNUNET_GETOPT_set_string, &issuer_key},
+ 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 */
diff --git a/src/credential/gnunet-service-credential.c b/src/credential/gnunet-service-credential.c
new file mode 100644
index 0000000000..de05926375
--- /dev/null
+++ b/src/credential/gnunet-service-credential.c
@@ -0,0 +1,425 @@
+/*
+ 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 "gnunet_protocols.h"
+
+// For Looking up GNS request
+#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>
+#include "gnunet_gns_service.h"
+
+
+
+
+#define GNUNET_CREDENTIAL_MAX_LENGTH 255
+
+/**
+ * DLL for record
+ */
+struct CredentialRecordEntry
+{
+ /**
+ * DLL
+ */
+ struct CredentialRecordEntry *next;
+
+ /**
+ * DLL
+ */
+ struct CredentialRecordEntry *prev;
+
+
+ /**
+ * Payload
+ */
+ struct GNUNET_CREDENTIAL_RecordData record_data;
+};
+
+/**
+ * Handle to a lookup operation from api
+ */
+struct ClientLookupHandle
+{
+
+ /**
+ * We keep these in a DLL.
+ */
+ struct ClientLookupHandle *next;
+
+ /**
+ * We keep these in a DLL.
+ */
+ struct ClientLookupHandle *prev;
+
+ /**
+ * Handle to the requesting client
+ */
+ struct GNUNET_SERVICE_Client *client;
+
+ /**
+ * Handle to GNS lookup
+ */
+ struct GNUNET_GNS_LookupRequest *lookup_request;
+
+ /**
+ * Authority public key
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * Credential Chain
+ */
+ struct CredentialRecordEntry *cred_chain_head;
+
+ /**
+ * Credential Chain
+ */
+ struct CredentialRecordEntry *cred_chain_tail;
+
+ /**
+ * request id
+ */
+ uint32_t request_id;
+
+};
+
+
+/**
+ * Head of the DLL.
+ */
+static struct ClientLookupHandle *clh_head;
+
+/**
+ * Tail of the DLL.
+ */
+static struct ClientLookupHandle *clh_tail;
+
+/**
+ * Handle to the statistics service
+ */
+static struct GNUNET_STATISTICS_Handle *statistics;
+
+
+
+/**
+ * Handle to GNS service.
+ */
+static struct GNUNET_GNS_Handle *gns;
+
+/**
+ * Task run during shutdown.
+ *
+ * @param cls unused
+ * @param tc unused
+ */
+static void
+shutdown_task (void *cls)
+{
+ struct ClientLookupHandle *clh;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Shutting down!\n");
+ while (NULL != (clh = clh_head))
+ {
+ //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
+ GNUNET_CONTAINER_DLL_remove (clh_head,
+ clh_tail,
+ clh);
+ GNUNET_free (clh);
+ }
+
+
+ if (NULL != statistics)
+ {
+ GNUNET_STATISTICS_destroy (statistics,
+ GNUNET_NO);
+ statistics = NULL;
+ }
+
+}
+
+/**
+ * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP message
+ *
+ * @param cls client sending the message
+ * @param l_msg message of type `struct LookupMessage`
+ * @return #GNUNET_OK if @a l_msg is well-formed
+ */
+static int
+check_lookup (void *cls,
+ const struct LookupMessage *l_msg)
+{
+ size_t msg_size;
+ const char* cred;
+
+ msg_size = ntohs (l_msg->header.size);
+ if (msg_size < sizeof (struct LookupMessage))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ cred = (const char *) &l_msg[1];
+ if ( ('\0' != cred[l_msg->header.size - sizeof (struct LookupMessage) - 1]) ||
+ (strlen (cred) > GNUNET_CREDENTIAL_MAX_LENGTH) )
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Reply to client with the result from our 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
+send_lookup_response (void* cls,
+ uint32_t rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+ struct ClientLookupHandle *clh = cls;
+ size_t len;
+ int i;
+ int cred_record_count;
+ struct GNUNET_MQ_Envelope *env;
+ struct LookupResultMessage *rmsg;
+ const struct GNUNET_CREDENTIAL_RecordData *crd;
+ struct CredentialRecordEntry *cr_entry;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending LOOKUP_RESULT message with %u results\n",
+ (unsigned int) rd_count);
+
+ 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 = rd[i].data;
+ /**
+ * TODO: Check for:
+ * - First time we come here subject must be subject prvided by client
+ * - After that is has to be the prev issuer
+ * - Terminate condition: issuer is clh->authority_key
+ *
+ * In any case:
+ * Append crd to result list of RecordData
+ */
+ cr_entry = GNUNET_new (struct CredentialRecordEntry);
+ cr_entry->record_data = *crd;
+ GNUNET_CONTAINER_DLL_insert_tail (clh->cred_chain_head,
+ clh->cred_chain_tail,
+ cr_entry);
+
+ }
+
+ /**
+ * Get serialized record data size
+ */
+ len = cred_record_count * sizeof (struct GNUNET_CREDENTIAL_RecordData);
+
+ /**
+ * Prepare a lookup result response message for the client
+ */
+ env = GNUNET_MQ_msg_extra (rmsg,
+ len,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP_RESULT);
+ //Assign id so that client can find associated request
+ rmsg->id = clh->request_id;
+ rmsg->cd_count = htonl (cred_record_count);
+
+ /**
+ * Get serialized record data
+ * Append at the end of rmsg
+ */
+ i = 0;
+ struct GNUNET_CREDENTIAL_RecordData *tmp_record = (struct GNUNET_CREDENTIAL_RecordData*) &rmsg[1];
+ for (cr_entry = clh->cred_chain_head; NULL != cr_entry; cr_entry = cr_entry->next)
+ {
+ memcpy (tmp_record,
+ &cr_entry->record_data,
+ sizeof (struct GNUNET_CREDENTIAL_RecordData));
+ tmp_record++;
+ }
+ GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(clh->client),
+ env);
+
+ GNUNET_CONTAINER_DLL_remove (clh_head, clh_tail, clh);
+
+ /**
+ * TODO:
+ * - Free DLL
+ * - Refactor into cleanup_handle() function for this
+ */
+ GNUNET_free (clh);
+
+ GNUNET_STATISTICS_update (statistics,
+ "Completed lookups", 1,
+ GNUNET_NO);
+ GNUNET_STATISTICS_update (statistics,
+ "Records resolved",
+ rd_count,
+ GNUNET_NO);
+}
+
+/**
+ * Handle lookup requests from client
+ *
+ * @param cls the closure
+ * @param client the client
+ * @param message the message
+ */
+static void
+handle_lookup (void *cls,
+ const struct LookupMessage *l_msg)
+{
+ char credential[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+ struct ClientLookupHandle *clh;
+ struct GNUNET_SERVICE_Client *client = cls;
+ char *credentialptr = credential;
+ const char *utf_in;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received LOOKUP message\n");
+
+ utf_in = (const char *) &l_msg[1];
+ GNUNET_STRINGS_utf8_tolower (utf_in, credentialptr);
+ clh = GNUNET_new (struct ClientLookupHandle);
+ GNUNET_CONTAINER_DLL_insert (clh_head, clh_tail, clh);
+ clh->client = client;
+ clh->request_id = l_msg->id;
+ clh->issuer_key = l_msg->issuer_key;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending LOOKUP_RESULT message with >%u results\n",
+ 0);
+
+ if (NULL == credential)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No credential provided\n");
+ send_lookup_response (clh, 0, NULL);
+ return;
+ }
+ clh->lookup_request = GNUNET_GNS_lookup (gns,
+ credential,
+ &l_msg->subject_key, //subject_pkey,
+ GNUNET_GNSRECORD_TYPE_CREDENTIAL,
+ GNUNET_GNS_LO_DEFAULT, //TODO configurable? credential.conf
+ NULL, //shorten_key, always NULL
+ &send_lookup_response,
+ clh);
+}
+
+
+/**
+ * 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"));
+ }
+
+ 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 (lookup,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP,
+ struct LookupMessage,
+ NULL),
+ GNUNET_MQ_handler_end());
+
+/* end of gnunet-service-credential.c */
diff --git a/src/credential/plugin_gnsrecord_credential.c b/src/credential/plugin_gnsrecord_credential.c
new file mode 100644
index 0000000000..6ae3b8980c
--- /dev/null
+++ b/src/credential/plugin_gnsrecord_credential.c
@@ -0,0 +1,257 @@
+/*
+ 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"
+
+
+/**
+ * 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_CREDENTIAL:
+ {
+ struct GNUNET_CREDENTIAL_RecordData cred;
+ char *cred_str;
+ char *subject_pkey;
+ char *issuer_pkey;
+ uint32_t cf; // Credential flags
+ uint32_t mdd; // Max delegation depth
+ if (data_size < sizeof (struct GNUNET_CREDENTIAL_RecordData))
+ return NULL; /* malformed */
+ memcpy (&cred,
+ data,
+ sizeof (cred));
+ cdata = data;
+ subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred.subject_key);
+ issuer_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred.issuer_key);
+ cf = ntohl (cred.credential_flags);
+ mdd = ntohl (cred.max_delegation_depth);
+
+ GNUNET_asprintf (&cred_str,
+ "%s %s %u %u %s",
+ subject_pkey,
+ issuer_pkey,
+ (unsigned int) cf,
+ (unsigned int) mdd,
+ &cdata[sizeof (cred)]);
+ GNUNET_free (subject_pkey);
+ GNUNET_free (issuer_pkey);
+
+
+
+ return cred_str;
+ }
+ default:
+ return NULL;
+ }
+}
+
+
+/**
+ * Convert human-readable version of a 'value' of a record to the binary
+ * representation.
+ *
+ * @param cls closure, unused
+ * @param type type of the record
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+static int
+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_CREDENTIAL:
+ {
+ struct GNUNET_CREDENTIAL_RecordData *cred;
+ unsigned int cf; // credential flags
+ unsigned int mdd; // max delegation depth
+
+ 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];
+
+ if (5 != SSCANF (s,
+ "%52s %52s %u %u %253s",
+ subject_pkey,
+ issuer_pkey,
+ &cf,
+ &mdd,
+ name))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Unable to parse CRED record string `%s'\n"),
+ s);
+ return GNUNET_SYSERR;
+ }
+ *data_size = sizeof (struct GNUNET_CREDENTIAL_RecordData) + strlen (name) + 1;
+ *data = cred = GNUNET_malloc (*data_size);
+ 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);
+ cred->credential_flags = htonl (cf);
+ cred->max_delegation_depth = htonl (mdd);
+ GNUNET_memcpy (&cred[1],
+ name,
+ strlen (name));
+
+
+ *data = GNUNET_strdup (s);
+ *data_size = strlen (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 },
+ { 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 */
diff --git a/src/credential/test_credential_lookup.sh b/src/credential/test_credential_lookup.sh
new file mode 100755
index 0000000000..216c281d7a
--- /dev/null
+++ b/src/credential/test_credential_lookup.sh
@@ -0,0 +1,40 @@
+#!/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`
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+TEST_CREDENTIAL="keySub keyIss credName"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C testsubject -c test_credential_lookup.conf
+
+#TODO1 Plugin serialization functions see REVERSE in gns/plugin_gnsrecord_gns.c
+gnunet-namestore -p -z testsubject -a -n newcred -t CRED -V $TEST_CREDENTIAL -e never -c test_credential_lookup.conf
+
+#TODO2 Add -z swich like in gnunet-gns
+RES_IP=`$DO_TIMEOUT gnunet-credential -z testsubject -s testsubject -u credName -c test_credential_lookup.conf`
+gnunet-namestore -z testsubject -d -n newcred -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
+
+#TODO3 proper test
+exit 0
+
+#if [ "$RES_IP" == "$TEST_CRED" ]
+#then
+# exit 0
+#else
+# echo "FAIL: Failed to resolve to proper IP, got $RES_IP."
+# exit 1
+#fi
diff --git a/src/include/gnunet_credential_service.h b/src/include/gnunet_credential_service.h
index 99d4161698..55deb786e1 100644
--- a/src/include/gnunet_credential_service.h
+++ b/src/include/gnunet_credential_service.h
@@ -34,6 +34,7 @@
#include "gnunet_util_lib.h"
#include "gnunet_gns_service.h"
+#include "gnunet_identity_service.h"
#ifdef __cplusplus
extern "C"
@@ -54,6 +55,44 @@ struct GNUNET_CREDENTIAL_Handle;
*/
struct GNUNET_CREDENTIAL_LookupRequest;
+/*
+* 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
+/*
+* Data stored in the credential record
+*/
+struct GNUNET_CREDENTIAL_RecordData {
+
+ /*
+ * Key of the
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+
+ uint32_t credential_flags GNUNET_PACKED;
+
+ uint32_t max_delegation_depth GNUNET_PACKED;
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+
/**
* Initialize the connection with the Credential service.
@@ -61,7 +100,7 @@ struct GNUNET_CREDENTIAL_LookupRequest;
* @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);
@@ -85,7 +124,7 @@ GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle);
typedef void (*GNUNET_CREDENTIAL_LookupResultProcessor) (void *cls,
struct GNUNET_IDENTITY_Ego *issuer,
uint16_t issuer_len,
- const struct GNUNET_CREDENTIAL_Value *value);
+ const struct GNUNET_CREDENTIAL_RecordData *data);
/**
@@ -102,7 +141,11 @@ 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,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
+ uint32_t credential_flags,
+ uint32_t max_delegation_depth,
+ GNUNET_CREDENTIAL_LookupResultProcessor proc,
void *proc_cls);
@@ -113,18 +156,18 @@ GNUNET_CREDENTIAL_lookup (struct GNUNET_CREDENTIAL_Handle *handle,
* @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 data the data of the credential
* @return handle to the queued request
*/
-struct GNUNET_CREDENTIAL_IssueRequest *
+/**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,
+ struct GNUNET_CREDENTIAL_Data *data,
GNUNET_CREDENTIAL_IssueResultProcessor proc,
void *proc_cls);
-
+*/
/**
* Remove a credential
*
@@ -134,6 +177,7 @@ GNUNET_CREDENTIAL_issue (struct GNUNET_CREDENTIAL_Handle *handle,
* @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,
@@ -141,7 +185,7 @@ GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle *handle,
const char *credential,
GNUNET_CREDENTIAL_IssueResultProcessor proc,
void *proc_cls);
-
+*/
/**
diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h
index 985ae1f7ab..7e0a1a9e96 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -109,10 +109,17 @@ extern "C"
#define GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA 65546
/**
+ * Record type for credential
+ */
+#define GNUNET_GNSRECORD_TYPE_CREDENTIAL 65547
+
+/**
* Record type for reverse lookups
*/
#define GNUNET_GNSRECORD_TYPE_REVERSE 65548
+
+
/**
* Flags that can be set for a record.
*/
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index db479d2350..3e16350c16 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2607,6 +2607,15 @@ extern "C"
#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT 964
+
+/**************************************************
+ *
+ * CREDENTIAL MESSAGE TYPES
+ */
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP 971
+
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP_RESULT 972
+
/******************************************************************************/