add credential
authorMartin Schanzenbach <mschanzenbach@posteo.de>
Thu, 10 Nov 2016 19:35:04 +0000 (20:35 +0100)
committerMartin Schanzenbach <mschanzenbach@posteo.de>
Thu, 10 Nov 2016 19:45:55 +0000 (20:45 +0100)
13 files changed:
configure.ac
src/Makefile.am
src/credential/Makefile.am [new file with mode: 0644]
src/credential/credential.conf.in [new file with mode: 0644]
src/credential/credential.h [new file with mode: 0644]
src/credential/credential_api.c [new file with mode: 0644]
src/credential/gnunet-credential.c [new file with mode: 0644]
src/credential/gnunet-service-credential.c [new file with mode: 0644]
src/credential/plugin_gnsrecord_credential.c [new file with mode: 0644]
src/credential/test_credential_lookup.sh [new file with mode: 0755]
src/include/gnunet_credential_service.h
src/include/gnunet_gnsrecord_lib.h
src/include/gnunet_protocols.h

index d839f8b4e62fe8b7589a36a6f0abe7b35dff8d11..1a24513929cdf45557881602ce286519a7acd183 100644 (file)
@@ -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
index 98ca70ae3254aaac9fbf570cdc26c06ac3a59e1f..2877cab0b8e7168c05de1c243b145be134462b19 100644 (file)
@@ -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 (file)
index 0000000..6469895
--- /dev/null
@@ -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 (file)
index 0000000..71f3066
--- /dev/null
@@ -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 (file)
index 0000000..597c34a
--- /dev/null
@@ -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 (file)
index 0000000..1efe2d0
--- /dev/null
@@ -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 (file)
index 0000000..363ed03
--- /dev/null
@@ -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 (file)
index 0000000..de05926
--- /dev/null
@@ -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 (file)
index 0000000..6ae3b89
--- /dev/null
@@ -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 (executable)
index 0000000..216c281
--- /dev/null
@@ -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
index 99d41616987cc3f2ec933d15e1fbef4573fae720..55deb786e15e9ba10290d91a53504b68b43be0ae 100644 (file)
@@ -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);
-
+*/
 
 
 /**
index 985ae1f7ab0d5489d6ffbc3b00644787bf119990..7e0a1a9e96708caf04d3579233df6f3bd9b4f005 100644 (file)
@@ -108,11 +108,18 @@ 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.
  */
index db479d2350d10815767d8aa4b2c6aaeef9bd29a1..3e16350c168030f5c99fed3fc45d129a74f26380 100644 (file)
@@ -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
+
 /******************************************************************************/