renamed identity-provider subsystem to reclaim
authorSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>
Thu, 19 Jul 2018 21:28:53 +0000 (23:28 +0200)
committerSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>
Thu, 19 Jul 2018 21:28:53 +0000 (23:28 +0200)
61 files changed:
configure.ac
po/POTFILES.in
src/Makefile.am
src/identity-attribute/Makefile.am [deleted file]
src/identity-attribute/identity_attribute.c [deleted file]
src/identity-attribute/identity_attribute.h [deleted file]
src/identity-attribute/plugin_identity_attribute_gnuid.c [deleted file]
src/identity-provider/.gitignore [deleted file]
src/identity-provider/Makefile.am [deleted file]
src/identity-provider/gnunet-idp.c [deleted file]
src/identity-provider/gnunet-service-identity-provider.c [deleted file]
src/identity-provider/identity-provider.conf [deleted file]
src/identity-provider/identity-token.conf [deleted file]
src/identity-provider/identity_provider.h [deleted file]
src/identity-provider/identity_provider_api.c [deleted file]
src/identity-provider/jwt.c [deleted file]
src/identity-provider/jwt.h [deleted file]
src/identity-provider/plugin_gnsrecord_identity_provider.c [deleted file]
src/identity-provider/plugin_identity_provider_sqlite.c [deleted file]
src/identity-provider/plugin_rest_identity_provider.c [deleted file]
src/identity-provider/plugin_rest_openid_connect.c [deleted file]
src/identity-provider/test_idp.conf [deleted file]
src/identity-provider/test_idp.sh [deleted file]
src/identity-provider/test_idp_attribute.sh [deleted file]
src/identity-provider/test_idp_consume.sh [deleted file]
src/identity-provider/test_idp_defaults.conf [deleted file]
src/identity-provider/test_idp_issue.sh [deleted file]
src/identity-provider/test_idp_revoke.sh [deleted file]
src/include/Makefile.am
src/include/gnunet_identity_attribute_lib.h [deleted file]
src/include/gnunet_identity_attribute_plugin.h [deleted file]
src/include/gnunet_identity_provider_plugin.h [deleted file]
src/include/gnunet_identity_provider_service.h [deleted file]
src/include/gnunet_protocols.h
src/include/gnunet_reclaim_attribute_lib.h [new file with mode: 0644]
src/include/gnunet_reclaim_attribute_plugin.h [new file with mode: 0644]
src/include/gnunet_reclaim_plugin.h [new file with mode: 0644]
src/include/gnunet_reclaim_service.h [new file with mode: 0644]
src/reclaim-attribute/Makefile.am [new file with mode: 0644]
src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c [new file with mode: 0644]
src/reclaim-attribute/reclaim_attribute.c [new file with mode: 0644]
src/reclaim-attribute/reclaim_attribute.h [new file with mode: 0644]
src/reclaim/.gitignore [new file with mode: 0644]
src/reclaim/Makefile.am [new file with mode: 0644]
src/reclaim/gnunet-reclaim.c [new file with mode: 0644]
src/reclaim/gnunet-service-reclaim.c [new file with mode: 0644]
src/reclaim/jwt.c [new file with mode: 0644]
src/reclaim/jwt.h [new file with mode: 0644]
src/reclaim/plugin_gnsrecord_reclaim.c [new file with mode: 0644]
src/reclaim/plugin_reclaim_sqlite.c [new file with mode: 0644]
src/reclaim/plugin_rest_openid_connect.c [new file with mode: 0644]
src/reclaim/plugin_rest_reclaim.c [new file with mode: 0644]
src/reclaim/reclaim.conf [new file with mode: 0644]
src/reclaim/reclaim.h [new file with mode: 0644]
src/reclaim/reclaim_api.c [new file with mode: 0644]
src/reclaim/test_reclaim.sh [new file with mode: 0755]
src/reclaim/test_reclaim_attribute.sh [new file with mode: 0755]
src/reclaim/test_reclaim_consume.sh [new file with mode: 0755]
src/reclaim/test_reclaim_defaults.conf [new file with mode: 0644]
src/reclaim/test_reclaim_issue.sh [new file with mode: 0755]
src/reclaim/test_reclaim_revoke.sh [new file with mode: 0755]

index c7314d76548ba277027488885c74641e04ae0311..535ce0ffeab0d02ee2febf7958904806b7a3e03f 100644 (file)
@@ -1759,8 +1759,8 @@ src/zonemaster/Makefile
 src/zonemaster/zonemaster.conf
 src/rest/Makefile
 src/abe/Makefile
-src/identity-attribute/Makefile
-src/identity-provider/Makefile
+src/reclaim-attribute/Makefile
+src/reclaim/Makefile
 pkgconfig/Makefile
 pkgconfig/gnunetarm.pc
 pkgconfig/gnunetats.pc
index 83c3c7bddf6f525a73a65145d5325e05b4734827..86235f8600aca1be4d06871680ab7374ce393ae8 100644 (file)
@@ -198,16 +198,6 @@ src/hello/hello.c
 src/hostlist/gnunet-daemon-hostlist.c
 src/hostlist/gnunet-daemon-hostlist_client.c
 src/hostlist/gnunet-daemon-hostlist_server.c
-src/identity-attribute/identity_attribute.c
-src/identity-attribute/plugin_identity_attribute_gnuid.c
-src/identity-provider/gnunet-idp.c
-src/identity-provider/gnunet-service-identity-provider.c
-src/identity-provider/identity_provider_api.c
-src/identity-provider/jwt.c
-src/identity-provider/plugin_gnsrecord_identity_provider.c
-src/identity-provider/plugin_identity_provider_sqlite.c
-src/identity-provider/plugin_rest_identity_provider.c
-src/identity-provider/plugin_rest_openid_connect.c
 src/identity/gnunet-identity.c
 src/identity/gnunet-service-identity.c
 src/identity/identity_api.c
@@ -297,6 +287,16 @@ src/psycutil/psyc_env.c
 src/psycutil/psyc_message.c
 src/psycutil/psyc_slicer.c
 src/pt/gnunet-daemon-pt.c
+src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c
+src/reclaim-attribute/reclaim_attribute.c
+src/reclaim/gnunet-reclaim.c
+src/reclaim/gnunet-service-reclaim.c
+src/reclaim/jwt.c
+src/reclaim/plugin_gnsrecord_reclaim.c
+src/reclaim/plugin_reclaim_sqlite.c
+src/reclaim/plugin_rest_openid_connect.c
+src/reclaim/plugin_rest_reclaim.c
+src/reclaim/reclaim_api.c
 src/regex/gnunet-daemon-regexprofiler.c
 src/regex/gnunet-regex-profiler.c
 src/regex/gnunet-regex-simulation-profiler.c
index 00f30adc3b838bbc5090f4949f725adc60720a95..4ded81891366e1b7e9fa1247e94d1b6fd344b2ff 100644 (file)
@@ -19,11 +19,13 @@ if HAVE_EXPERIMENTAL
   social 
 #  dv (FTBFS)
 if HAVE_ABE
+if HAVE_JSON
  EXP_DIR += \
     abe \
     credential \
-    identity-attribute \
-    identity-provider 
+    reclaim-attribute \
+    reclaim 
+endif
 endif
 if HAVE_JSON
  EXP_DIR += \
diff --git a/src/identity-attribute/Makefile.am b/src/identity-attribute/Makefile.am
deleted file mode 100644 (file)
index 2c73a44..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-# This Makefile.am is in the public domain
-AM_CPPFLAGS = -I$(top_srcdir)/src/include
-
-plugindir = $(libdir)/gnunet
-
-pkgcfgdir= $(pkgdatadir)/config.d/
-
-libexecdir= $(pkglibdir)/libexec/
-
-if MINGW
-  WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
-endif
-
-if USE_COVERAGE
-  AM_CFLAGS = --coverage -O0
-  XLIBS = -lgcov
-endif
-
-lib_LTLIBRARIES = \
-  libgnunetidentityattribute.la
-
-libgnunetidentityattribute_la_SOURCES = \
-  identity_attribute.c
-libgnunetidentityattribute_la_LIBADD = \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(GN_LIBINTL)
-libgnunetidentityattribute_la_LDFLAGS = \
-  $(GN_LIB_LDFLAGS) $(WINFLAGS) \
-  -version-info 0:0:0
-
-
-plugin_LTLIBRARIES = \
-  libgnunet_plugin_identity_attribute_gnuid.la
-
-
-libgnunet_plugin_identity_attribute_gnuid_la_SOURCES = \
-  plugin_identity_attribute_gnuid.c
-libgnunet_plugin_identity_attribute_gnuid_la_LIBADD = \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(LTLIBINTL)
-libgnunet_plugin_identity_attribute_gnuid_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
-
diff --git a/src/identity-attribute/identity_attribute.c b/src/identity-attribute/identity_attribute.c
deleted file mode 100644 (file)
index 7d47c46..0000000
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
-      This file is part of GNUnet
-      Copyright (C) 2010-2015 GNUnet e.V.
-
-      GNUnet is free software: you can redistribute it and/or modify it
-      under the terms of the GNU Affero General Public License as published
-      by the Free Software Foundation, either version 3 of the License,
-      or (at your option) any later version.
-
-      GNUnet is distributed in the hope that it will be useful, but
-      WITHOUT ANY WARRANTY; without even the implied warranty of
-      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-      Affero General Public License for more details.
-     
-      You should have received a copy of the GNU Affero General Public License
-      along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * @file identity-attribute/identity_attribute.c
- * @brief helper library to manage identity attributes
- * @author Martin Schanzenbach
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "identity_attribute.h"
-#include "gnunet_identity_attribute_plugin.h"
-
-/**
- * Handle for a plugin
- */
-struct Plugin
-{
-  /**
-   * Name of the plugin
-   */
-  char *library_name;
-
-  /**
-   * Plugin API
-   */
-  struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api;
-};
-
-/**
- * Plugins
- */
-static struct Plugin **attr_plugins;
-
-/**
- * Number of plugins
- */
-static unsigned int num_plugins;
-
-/**
- * Init canary
- */
-static int initialized;
-
-/**
- * Add a plugin
- */
-static void
-add_plugin (void* cls,
-            const char *library_name,
-            void *lib_ret)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api = lib_ret;
-  struct Plugin *plugin;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Loading attribute plugin `%s'\n",
-              library_name);
-  plugin = GNUNET_new (struct Plugin);
-  plugin->api = api;
-  plugin->library_name = GNUNET_strdup (library_name);
-  GNUNET_array_append (attr_plugins, num_plugins, plugin);
-}
-
-/**
- * Load plugins
- */
-static void
-init()
-{
-  if (GNUNET_YES == initialized)
-    return;
-  initialized = GNUNET_YES;
-  GNUNET_PLUGIN_load_all ("libgnunet_plugin_identity_attribute_", NULL,
-                          &add_plugin, NULL);
-}
-
-/**
- * Convert a type name to the corresponding number
- *
- * @param typename name to convert
- * @return corresponding number, UINT32_MAX on error
- */
-uint32_t
-GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (const char *typename)
-{
-  unsigned int i;
-  struct Plugin *plugin;
-  uint32_t ret;
-  
-  init ();
-  for (i = 0; i < num_plugins; i++)
-  {
-    plugin = attr_plugins[i];
-    if (UINT32_MAX != (ret = plugin->api->typename_to_number (plugin->api->cls,
-                                                              typename)))
-      return ret;
-  }
-  return UINT32_MAX;
-}
-
-/**
- * Convert a type number to the corresponding type string
- *
- * @param type number of a type
- * @return corresponding typestring, NULL on error
- */
-const char*
-GNUNET_IDENTITY_ATTRIBUTE_number_to_typename (uint32_t type)
-{
-  unsigned int i;
-  struct Plugin *plugin;
-  const char *ret;
-
-  init ();
-  for (i = 0; i < num_plugins; i++)
-  {
-    plugin = attr_plugins[i];
-    if (NULL != (ret = plugin->api->number_to_typename (plugin->api->cls,
-                                                        type)))
-      return ret;
-  }
-  return NULL;
-}
-
-/**
- * Convert human-readable version of a 'claim' of an attribute to the binary
- * representation
- *
- * @param type type of the claim
- * @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
- */
-int
-GNUNET_IDENTITY_ATTRIBUTE_string_to_value (uint32_t type,
-                                           const char *s,
-                                           void **data,
-                                           size_t *data_size)
-{
-  unsigned int i;
-  struct Plugin *plugin;
-
-  init ();
-  for (i = 0; i < num_plugins; i++)
-  {
-    plugin = attr_plugins[i];
-    if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
-                                                   type,
-                                                   s,
-                                                   data,
-                                                   data_size))
-      return GNUNET_OK;
-  }
-  return GNUNET_SYSERR;
-}
-
-/**
- * Convert the 'claim' of an attribute to a string
- *
- * @param type the type of attribute
- * @param data claim in binary encoding
- * @param data_size number of bytes in @a data
- * @return NULL on error, otherwise human-readable representation of the claim
- */
-char *
-GNUNET_IDENTITY_ATTRIBUTE_value_to_string (uint32_t type,
-                                           const void* data,
-                                           size_t data_size)
-{
-  unsigned int i;
-  struct Plugin *plugin;
-  char *ret;
-
-  init();
-  for (i = 0; i < num_plugins; i++)
-  {
-    plugin = attr_plugins[i];
-    if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
-                                                     type,
-                                                     data,
-                                                     data_size)))
-      return ret;
-  }
-  return NULL;
-}
-
-/**
- * Create a new attribute.
- *
- * @param attr_name the attribute name
- * @param type the attribute type
- * @param data the attribute value
- * @param data_size the attribute value size
- * @return the new attribute
- */
-struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
-GNUNET_IDENTITY_ATTRIBUTE_claim_new (const char* attr_name,
-               uint32_t type,
-               const void* data,
-               size_t data_size)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
-  char *write_ptr;
-
-  attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim) +
-                        strlen (attr_name) + 1 +
-                        data_size);
-  attr->type = type;
-  attr->data_size = data_size;
-  attr->version = 0;
-  write_ptr = (char*)&attr[1];
-  GNUNET_memcpy (write_ptr,
-                 attr_name,
-                 strlen (attr_name) + 1);
-  attr->name = write_ptr;
-  write_ptr += strlen (attr->name) + 1;
-  GNUNET_memcpy (write_ptr,
-                 data,
-                 data_size);
-  attr->data = write_ptr;
-  return attr;
-}
-
-/**
- * Add a new claim list entry.
- *
- * @param claim_list the attribute name
- * @param attr_name the attribute name
- * @param type the attribute type
- * @param data the attribute value
- * @param data_size the attribute value size
- * @return
- */
-void
-GNUNET_IDENTITY_ATTRIBUTE_list_add (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *claim_list,
-                                   const char* attr_name,
-                                   uint32_t type,
-                                   const void* data,
-                                   size_t data_size)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-  le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
-  le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr_name,
-                                              type,
-                                              data,
-                                              data_size);
-  GNUNET_CONTAINER_DLL_insert (claim_list->list_head,
-                              claim_list->list_tail,
-                              le);
-}
-
-size_t
-GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-  size_t len = 0;
-  for (le = attrs->list_head; NULL != le; le = le->next)
-    len += GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (le->claim);
-  return len; 
-}
-
-size_t
-GNUNET_IDENTITY_ATTRIBUTE_list_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
-                          char *result)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-  size_t len;
-  size_t total_len;
-  char* write_ptr;
-
-  write_ptr = result;
-  total_len = 0;
-  for (le = attrs->list_head; NULL != le; le = le->next)
-  {
-    len = GNUNET_IDENTITY_ATTRIBUTE_serialize (le->claim,
-                               write_ptr);
-    total_len += len;
-    write_ptr += len;
-  }
-  return total_len;
-}
-
-struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *
-GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (const char* data,
-                       size_t data_size)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-  size_t attr_len;
-  const char* read_ptr;
-
-  if (data_size < sizeof (struct Attribute))
-    return NULL;
-  
-  attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
-  read_ptr = data;
-  while (((data + data_size) - read_ptr) >= sizeof (struct Attribute))
-  {
-
-    le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
-    le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (read_ptr,
-                                           data_size - (read_ptr - data));
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Deserialized attribute %s\n", le->claim->name);
-    GNUNET_CONTAINER_DLL_insert (attrs->list_head,
-                                 attrs->list_tail,
-                                 le);
-    attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (le->claim);
-    read_ptr += attr_len;
-  }
-  return attrs;
-}
-
-struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList*
-GNUNET_IDENTITY_ATTRIBUTE_list_dup (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *result_le;
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *result;
-
-  result = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
-  for (le = attrs->list_head; NULL != le; le = le->next)
-  {
-    result_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
-    result_le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (le->claim->name,
-                                                     le->claim->type,
-                                                     le->claim->data,
-                                                     le->claim->data_size);
-    GNUNET_CONTAINER_DLL_insert (result->list_head,
-                                 result->list_tail,
-                                 result_le);
-  }
-  return result;
-}
-
-
-void
-GNUNET_IDENTITY_ATTRIBUTE_list_destroy (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *tmp_le;
-
-  for (le = attrs->list_head; NULL != le;)
-  {
-    GNUNET_free (le->claim);
-    tmp_le = le;
-    le = le->next;
-    GNUNET_free (tmp_le);
-  }
-  GNUNET_free (attrs);
-
-}
-
-size_t
-GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
-{
-  return sizeof (struct Attribute) 
-    + strlen (attr->name)
-    + attr->data_size;
-}
-
-size_t
-GNUNET_IDENTITY_ATTRIBUTE_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
-                     char *result)
-{
-  size_t data_len_ser;
-  size_t name_len;
-  struct Attribute *attr_ser;
-  char* write_ptr;
-
-  attr_ser = (struct Attribute*)result;
-  attr_ser->attribute_type = htons (attr->type);
-  attr_ser->attribute_version = htonl (attr->version);
-  name_len = strlen (attr->name);
-  attr_ser->name_len = htons (name_len);
-  write_ptr = (char*)&attr_ser[1];
-  GNUNET_memcpy (write_ptr, attr->name, name_len);
-  write_ptr += name_len;
-  //TODO plugin-ize
-  //data_len_ser = plugin->serialize_attribute_value (attr,
-  //                                                  &attr_ser[1]);
-  data_len_ser = attr->data_size;
-  GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
-  attr_ser->data_size = htons (data_len_ser);
-
-  return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
-}
-
-struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
-GNUNET_IDENTITY_ATTRIBUTE_deserialize (const char* data,
-                       size_t data_size)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
-  struct Attribute *attr_ser;
-  size_t data_len;
-  size_t name_len;
-  char* write_ptr;
-
-  if (data_size < sizeof (struct Attribute))
-    return NULL;
-
-  attr_ser = (struct Attribute*)data;
-  data_len = ntohs (attr_ser->data_size);
-  name_len = ntohs (attr_ser->name_len);
-  attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim)
-                        + data_len + name_len + 1);
-  attr->type = ntohs (attr_ser->attribute_type);
-  attr->version = ntohl (attr_ser->attribute_version);
-  attr->data_size = ntohs (attr_ser->data_size);
-
-  write_ptr =  (char*)&attr[1];
-  GNUNET_memcpy (write_ptr,
-                 &attr_ser[1],
-                 name_len);
-  write_ptr[name_len] = '\0';
-  attr->name = write_ptr;
-
-  write_ptr += name_len + 1;
-  GNUNET_memcpy (write_ptr,
-                 (char*)&attr_ser[1] + name_len,
-                 attr->data_size);
-  attr->data = write_ptr;
-  return attr;
-
-}
-
-/* end of identity_attribute.c */
diff --git a/src/identity-attribute/identity_attribute.h b/src/identity-attribute/identity_attribute.h
deleted file mode 100644 (file)
index 2346dcd..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 GNUnet e.V.
-
-   GNUnet is free software: you can redistribute it and/or modify it
-   under the terms of the GNU Affero General Public License as published
-   by the Free Software Foundation, either version 3 of the License,
-   or (at your option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Affero General Public License for more details.
-  
-   You should have received a copy of the GNU Affero General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-   */
-/**
- * @author Martin Schanzenbach
- * @file identity-attribute/identity_attribute.h
- * @brief GNUnet Identity attributes
- *
- */
-#ifndef IDENTITY_ATTRIBUTE_H
-#define IDENTITY_ATTRIBUTE_H
-
-#include "gnunet_identity_provider_service.h"
-
-struct Attribute
-{
-  /**
-   * Attribute type
-   */
-  uint32_t attribute_type;
-
-  /**
-   * Attribute version
-   */
-  uint32_t attribute_version;
-
-  /**
-   * Name length
-   */
-  uint32_t name_len;
-  
-  /**
-   * Data size
-   */
-  uint32_t data_size;
-
-  //followed by data_size Attribute value data
-};
-
-#endif
diff --git a/src/identity-attribute/plugin_identity_attribute_gnuid.c b/src/identity-attribute/plugin_identity_attribute_gnuid.c
deleted file mode 100644 (file)
index c09b167..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
-     This file is part of GNUnet
-     Copyright (C) 2013, 2014, 2016 GNUnet e.V.
-
-     GNUnet is free software: you can redistribute it and/or modify it
-     under the terms of the GNU Affero General Public License as published
-     by the Free Software Foundation, either version 3 of the License,
-     or (at your option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     Affero General Public License for more details.
-    
-     You should have received a copy of the GNU Affero General Public License
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file identity-attribute/plugin_identity_attribute_gnuid.c
- * @brief identity attribute plugin to provide the API for fundamental 
- *                 attribute types.
- *
- * @author Martin Schanzenbach
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_identity_attribute_plugin.h"
-#include <inttypes.h>
-
-
-/**
- * Convert the 'value' of an attribute to a string.
- *
- * @param cls closure, unused
- * @param type type of the attribute
- * @param data value in binary encoding
- * @param data_size number of bytes in @a data
- * @return NULL on error, otherwise human-readable representation of the value
- */
-static char *
-gnuid_value_to_string (void *cls,
-                     uint32_t type,
-                     const void *data,
-                     size_t data_size)
-{
-
-  switch (type)
-  {
-  case GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING:
-    return GNUNET_strndup (data, data_size);
-  default:
-    return NULL;
-  }
-}
-
-
-/**
- * Convert human-readable version of a 'value' of an attribute to the binary
- * representation.
- *
- * @param cls closure, unused
- * @param type type of the attribute
- * @param s human-readable string
- * @param data set to value in binary encoding (will be allocated)
- * @param data_size set to number of bytes in @a data
- * @return #GNUNET_OK on success
- */
-static int
-gnuid_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_IDENTITY_ATTRIBUTE_TYPE_STRING:
-      *data = GNUNET_strdup (s);
-      *data_size = strlen (s);
-      return GNUNET_OK;
-    default:
-      return GNUNET_SYSERR;
-  }
-}
-
-
-/**
- * Mapping of attribute type numbers to human-readable
- * attribute type names.
- */
-static struct {
-  const char *name;
-  uint32_t number;
-} gnuid_name_map[] = {
-  { "STRING",  GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING },
-  { NULL, UINT32_MAX }
-};
-
-
-/**
- * Convert a type name to the corresponding number.
- *
- * @param cls closure, unused
- * @param gnuid_typename name to convert
- * @return corresponding number, UINT32_MAX on error
- */
-static uint32_t
-gnuid_typename_to_number (void *cls,
-                        const char *gnuid_typename)
-{
-  unsigned int i;
-
-  i=0;
-  while ( (NULL != gnuid_name_map[i].name) &&
-          (0 != strcasecmp (gnuid_typename,
-                            gnuid_name_map[i].name)) )
-    i++;
-  return gnuid_name_map[i].number;
-}
-
-
-/**
- * Convert a type number (i.e. 1) to the corresponding type string
- *
- * @param cls closure, unused
- * @param type number of a type to convert
- * @return corresponding typestring, NULL on error
- */
-static const char *
-gnuid_number_to_typename (void *cls,
-                        uint32_t type)
-{
-  unsigned int i;
-
-  i=0;
-  while ( (NULL != gnuid_name_map[i].name) &&
-          (type != gnuid_name_map[i].number) )
-    i++;
-  return gnuid_name_map[i].name;
-}
-
-
-/**
- * Entry point for the plugin.
- *
- * @param cls NULL
- * @return the exported block API
- */
-void *
-libgnunet_plugin_identity_attribute_gnuid_init (void *cls)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api;
-
-  api = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions);
-  api->value_to_string = &gnuid_value_to_string;
-  api->string_to_value = &gnuid_string_to_value;
-  api->typename_to_number = &gnuid_typename_to_number;
-  api->number_to_typename = &gnuid_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_identity_attribute_gnuid_done (void *cls)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api = cls;
-
-  GNUNET_free (api);
-  return NULL;
-}
-
-/* end of plugin_identity_attribute_type_gnuid.c */
diff --git a/src/identity-provider/.gitignore b/src/identity-provider/.gitignore
deleted file mode 100644 (file)
index ef77fcc..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-gnunet-service-identity-provider
-gnunet-identity-token
diff --git a/src/identity-provider/Makefile.am b/src/identity-provider/Makefile.am
deleted file mode 100644 (file)
index 2eb6995..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-# This Makefile.am is in the public domain
-AM_CPPFLAGS = -I$(top_srcdir)/src/include
-
- plugindir = $(libdir)/gnunet
-
-if MINGW
- WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
-endif
-
-if USE_COVERAGE
-  AM_CFLAGS = --coverage -O0
-  XLIB = -lgcov
-endif
-
-if HAVE_SQLITE
-SQLITE_PLUGIN = libgnunet_plugin_identity_provider_sqlite.la
-endif
-
-EXTRA_DIST = \
-  test_idp_defaults.conf \
-       test_idp.conf \
-       $(check_SCRIPTS)
-
-pkgcfgdir= $(pkgdatadir)/config.d/
-
-libexecdir= $(pkglibdir)/libexec/
-
-pkgcfg_DATA = \
-  identity-provider.conf
-
-lib_LTLIBRARIES = \
-  libgnunetidentityprovider.la
-plugin_LTLIBRARIES = \
-       libgnunet_plugin_rest_identity_provider.la \
-       libgnunet_plugin_rest_openid_connect.la \
-  libgnunet_plugin_gnsrecord_identity_provider.la \
-       $(SQLITE_PLUGIN)
-
-bin_PROGRAMS = \
- gnunet-idp
-
-libexec_PROGRAMS = \
- gnunet-service-identity-provider
-
-libgnunet_plugin_gnsrecord_identity_provider_la_SOURCES = \
-  plugin_gnsrecord_identity_provider.c
-libgnunet_plugin_gnsrecord_identity_provider_la_LIBADD = \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(LTLIBINTL)
-libgnunet_plugin_gnsrecord_identity_provider_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
-libgnunet_plugin_identity_provider_sqlite_la_SOURCES = \
-  plugin_identity_provider_sqlite.c
-libgnunet_plugin_identity_provider_sqlite_la_LIBADD = \
-  libgnunetidentityprovider.la  \
-  $(top_builddir)/src/sq/libgnunetsq.la \
-  $(top_builddir)/src/statistics/libgnunetstatistics.la \
-  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \
-  $(LTLIBINTL)
-libgnunet_plugin_identity_provider_sqlite_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
-
-
-gnunet_service_identity_provider_SOURCES = \
- gnunet-service-identity-provider.c
-gnunet_service_identity_provider_LDADD = \
- $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/namestore/libgnunetnamestore.la \
- $(top_builddir)/src/identity/libgnunetidentity.la \
- $(top_builddir)/src/statistics/libgnunetstatistics.la \
- $(top_builddir)/src/abe/libgnunetabe.la \
- $(top_builddir)/src/credential/libgnunetcredential.la \
- $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
- libgnunetidentityprovider.la \
- $(top_builddir)/src/gns/libgnunetgns.la \
- $(GN_LIBINTL)
-
-libgnunetidentityprovider_la_SOURCES = \
- identity_provider_api.c \
- identity_provider.h
-libgnunetidentityprovider_la_LIBADD = \
-  $(top_builddir)/src/util/libgnunetutil.la \
-       $(GN_LIBINTL) $(XLIB)
-libgnunetidentityprovider_la_LDFLAGS = \
-       $(GN_LIB_LDFLAGS)  $(WINFLAGS) \
-       -version-info 0:0:0
-
-libgnunet_plugin_rest_identity_provider_la_SOURCES = \
-  plugin_rest_identity_provider.c \
-       jwt.c
-libgnunet_plugin_rest_identity_provider_la_LIBADD = \
-       $(top_builddir)/src/identity/libgnunetidentity.la \
-       libgnunetidentityprovider.la \
-       $(top_builddir)/src/rest/libgnunetrest.la \
-       $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
-       $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
-       $(top_builddir)/src/namestore/libgnunetnamestore.la \
-  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
-  $(LTLIBINTL) -ljansson -lmicrohttpd
-libgnunet_plugin_rest_identity_provider_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
-libgnunet_plugin_rest_openid_connect_la_SOURCES = \
-  plugin_rest_openid_connect.c \
-       jwt.c
-libgnunet_plugin_rest_openid_connect_la_LIBADD = \
-       $(top_builddir)/src/identity/libgnunetidentity.la \
-       libgnunetidentityprovider.la \
-       $(top_builddir)/src/rest/libgnunetrest.la \
-       $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
-       $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
-       $(top_builddir)/src/namestore/libgnunetnamestore.la \
-  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
-  $(LTLIBINTL) -ljansson -lmicrohttpd
-libgnunet_plugin_rest_openid_connect_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
-gnunet_idp_SOURCES = \
- gnunet-idp.c
-gnunet_idp_LDADD = \
-  $(top_builddir)/src/util/libgnunetutil.la \
-       $(top_builddir)/src/namestore/libgnunetnamestore.la \
-       libgnunetidentityprovider.la \
-       $(top_builddir)/src/identity/libgnunetidentity.la \
-       $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
-  $(GN_LIBINTL)
-
-check_SCRIPTS = \
-       test_idp_attribute.sh \
-       test_idp_issue.sh \
-       test_idp_consume.sh \
-  test_idp_revoke.sh
-
-if ENABLE_TEST_RUN
- AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
- TESTS = $(check_SCRIPTS)
-endif
diff --git a/src/identity-provider/gnunet-idp.c b/src/identity-provider/gnunet-idp.c
deleted file mode 100644 (file)
index 79e4f8d..0000000
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 GNUnet e.V.
-
-   GNUnet is free software: you can redistribute it and/or modify it
-   under the terms of the GNU Affero General Public License as published
-   by the Free Software Foundation, either version 3 of the License,
-   or (at your option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Affero General Public License for more details.
-  
-   You should have received a copy of the GNU Affero General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-   */
-/**
- * @author Martin Schanzenbach
- * @file src/identity-provider/gnunet-idp.c
- * @brief Identity Provider utility
- *
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_namestore_service.h"
-#include "gnunet_identity_provider_service.h"
-#include "gnunet_identity_service.h"
-#include "gnunet_signatures.h"
-
-/**
- * return value
- */
-static int ret;
-
-/**
- * List attribute flag
- */
-static int list;
-
-/**
- * Relying party
- */
-static char* rp;
-
-/**
- * The attribute
- */
-static char* attr_name;
-
-/**
- * Attribute value
- */
-static char* attr_value;
-
-/**
- * Attributes to issue
- */
-static char* issue_attrs;
-
-/**
- * Ticket to consume
- */
-static char* consume_ticket;
-
-/**
- * Attribute type
- */
-static char* type_str;
-
-/**
- * Ticket to revoke
- */
-static char* revoke_ticket;
-
-/**
- * Ego name
- */
-static char* ego_name;
-
-/**
- * Identity handle
- */
-static struct GNUNET_IDENTITY_Handle *identity_handle;
-
-/**
- * IdP handle
- */
-static struct GNUNET_IDENTITY_PROVIDER_Handle *idp_handle;
-
-/**
- * IdP operation
- */
-static struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
-
-/**
- * Attribute iterator
- */
-static struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_iterator;
-
-/**
- * Master ABE key
- */
-static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
-
-/**
- * ego private key
- */
-static const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey;
-
-/**
- * rp public key
- */
-static struct GNUNET_CRYPTO_EcdsaPublicKey rp_key;
-
-/**
- * Ticket to consume
- */
-static struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
-
-/**
- * Attribute list
- */
-static struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attr_list;
-
-/**
- * Attribute expiration interval
- */
-static struct GNUNET_TIME_Relative exp_interval;
-
-/**
- * Timeout task
- */
-static struct GNUNET_SCHEDULER_Task *timeout;
-
-static void
-do_cleanup(void *cls)
-{
-  if (NULL != timeout)
-    GNUNET_SCHEDULER_cancel (timeout);
-  if (NULL != idp_op)
-    GNUNET_IDENTITY_PROVIDER_cancel (idp_op);
-  if (NULL != attr_iterator)
-    GNUNET_IDENTITY_PROVIDER_get_attributes_stop (attr_iterator);
-  if (NULL != idp_handle)
-    GNUNET_IDENTITY_PROVIDER_disconnect (idp_handle);
-  if (NULL != identity_handle)
-    GNUNET_IDENTITY_disconnect (identity_handle);
-  if (NULL != abe_key)
-    GNUNET_free (abe_key);
-  if (NULL != attr_list)
-    GNUNET_free (attr_list);
-}
-
-static void
-ticket_issue_cb (void* cls,
-                 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
-{
-  char* ticket_str;
-  idp_op = NULL;
-  if (NULL != ticket) {
-    ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
-                                                      sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
-    printf("%s\n",
-           ticket_str);
-    GNUNET_free (ticket_str);
-  }
-  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
-}
-
-static void
-store_attr_cont (void *cls,
-                 int32_t success,
-                 const char*emsg)
-{
-  idp_op = NULL;
-  if (GNUNET_SYSERR == success) {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "%s\n", emsg);
-  }
-  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
-}
-
-static void
-process_attrs (void *cls,
-         const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-         const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
-{
-  char *value_str;
-  if (NULL == identity)
-  {
-    idp_op = NULL;
-    GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
-    return;
-  }
-  if (NULL == attr)
-  {
-    ret = 1;
-    return;
-  }
-  value_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type,
-                                                     attr->data,
-                                                     attr->data_size);
-  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-              "%s: %s\n", attr->name, value_str);
-}
-
-
-static void
-iter_error (void *cls)
-{
-  attr_iterator = NULL;
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Failed to iterate over attributes\n");
-  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
-}
-
-static void
-timeout_task (void *cls)
-{
-  timeout = NULL;
-  ret = 1;
-  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-              "Timeout\n");
-  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
-}
-
-static void
-process_rvk (void *cls, int success, const char* msg)
-{
-  idp_op = NULL;
-  if (GNUNET_OK != success)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                "Revocation failed.\n");
-    ret = 1;
-  }
-  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
-}
-
-static void
-iter_finished (void *cls)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
-  char *data;
-  size_t data_size;
-  int type;
-
-  attr_iterator = NULL;
-  if (list)
-  {
-    GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
-    return;
-  }
-
-  if (issue_attrs)
-  {
-    idp_op = GNUNET_IDENTITY_PROVIDER_ticket_issue (idp_handle,
-                                                    pkey,
-                                                    &rp_key,
-                                                    attr_list,
-                                                    &ticket_issue_cb,
-                                                    NULL);
-    return;
-  }
-  if (consume_ticket)
-  {
-    idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (idp_handle,
-                                                      pkey,
-                                                      &ticket,
-                                                      &process_attrs,
-                                                      NULL);
-    timeout = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10),
-                                            &timeout_task,
-                                            NULL);
-    return;
-  }
-  if (revoke_ticket)
-  {
-    idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (idp_handle,
-                                                     pkey,
-                                                     &ticket,
-                                                     &process_rvk,
-                                                     NULL);
-    return;
-  }
-  if (attr_name)
-  {
-    if (NULL == type_str)
-      type = GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING;
-    else
-      type = GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (type_str);
-
-    GNUNET_assert (GNUNET_SYSERR != GNUNET_IDENTITY_ATTRIBUTE_string_to_value (type,
-                                                                               attr_value,
-                                                                               (void**)&data,
-                                                                               &data_size));
-    claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr_name,
-                                                 type,
-                                                 data,
-                                                 data_size);
-    idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (idp_handle,
-                                                       pkey,
-                                                       claim,
-                                                       &exp_interval,
-                                                       &store_attr_cont,
-                                                       NULL);
-    return;
-  }
-  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
-}
-
-static void
-iter_cb (void *cls,
-         const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-         const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-  char *attrs_tmp;
-  char *attr_str;
-
-  if (issue_attrs)
-  {
-    attrs_tmp = GNUNET_strdup (issue_attrs);
-    attr_str = strtok (attrs_tmp, ",");
-    while (NULL != attr_str) {
-      if (0 != strcmp (attr_str, attr->name)) {
-        attr_str = strtok (NULL, ",");
-        continue;
-      }
-      le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
-      le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr->name,
-                                                       attr->type,
-                                                       attr->data,
-                                                       attr->data_size);
-      GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
-                                   attr_list->list_tail,
-                                   le);
-      break;
-    }
-    GNUNET_free (attrs_tmp);
-  } else if (list) {
-    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                "%s: %s\n", attr->name, (char*)attr->data);
-  }
-  GNUNET_IDENTITY_PROVIDER_get_attributes_next (attr_iterator);
-}
-
-static void
-ego_iter_finished (void *cls)
-{
-  if (NULL == pkey)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                "Ego %s not found\n", ego_name);
-    return;
-  }
-
-  if (NULL != rp)
-    GNUNET_CRYPTO_ecdsa_public_key_from_string (rp,
-                                                strlen (rp),
-                                                &rp_key);
-  if (NULL != consume_ticket)
-    GNUNET_STRINGS_string_to_data (consume_ticket,
-                                   strlen (consume_ticket),
-                                   &ticket,
-                                   sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
-  if (NULL != revoke_ticket)
-    GNUNET_STRINGS_string_to_data (revoke_ticket,
-                                   strlen (revoke_ticket),
-                                   &ticket,
-                                   sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
-
-
-  attr_list = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
-
-  attr_iterator = GNUNET_IDENTITY_PROVIDER_get_attributes_start (idp_handle,
-                                                                 pkey,
-                                                                 &iter_error,
-                                                                 NULL,
-                                                                 &iter_cb,
-                                                                 NULL,
-                                                                 &iter_finished,
-                                                                 NULL);
-
-
-}
-
-static int init = GNUNET_YES;
-
-static void
-ego_cb (void *cls,
-        struct GNUNET_IDENTITY_Ego *ego,
-        void **ctx,
-        const char *name)
-{
-  if (NULL == name) {
-    if (GNUNET_YES == init) {
-      init = GNUNET_NO;
-      GNUNET_SCHEDULER_add_now (&ego_iter_finished, NULL);
-    }
-    return;
-  }
-  if (0 != strcmp (name, ego_name))
-    return;
-  pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
-}
-
-
-static void
-run (void *cls,
-     char *const *args,
-     const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  ret = 0;
-  if (NULL == ego_name)
-  {
-    ret = 1;
-    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                _("Ego is required\n"));
-    return;
-  }
-
-  if ( (NULL == attr_value) && (NULL != attr_name) )
-  {
-    ret = 1;
-    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                _("Attribute value missing!\n"));
-    return;
-  }
-
-  if ( (NULL == rp) && (NULL != issue_attrs) )
-  {
-    ret = 1;
-    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                _("Requesting party key is required!\n"));
-    return;
-  }
-
-  idp_handle = GNUNET_IDENTITY_PROVIDER_connect (c);
-  //Get Ego
-  identity_handle = GNUNET_IDENTITY_connect (c,
-                                             &ego_cb,
-                                             NULL);
-
-
-}
-
-
-int
-main(int argc, char *const argv[])
-{
-  exp_interval = GNUNET_TIME_UNIT_HOURS;
-  struct GNUNET_GETOPT_CommandLineOption options[] = {
-
-    GNUNET_GETOPT_option_string ('a',
-                                 "add",
-                                 NULL,
-                                 gettext_noop ("Add attribute"),
-                                 &attr_name),
-
-    GNUNET_GETOPT_option_string ('V',
-                                 "value",
-                                 NULL,
-                                 gettext_noop ("Attribute value"),
-                                 &attr_value),
-    GNUNET_GETOPT_option_string ('e',
-                                 "ego",
-                                 NULL,
-                                 gettext_noop ("Ego"),
-                                 &ego_name),
-    GNUNET_GETOPT_option_string ('r',
-                                 "rp",
-                                 NULL,
-                                 gettext_noop ("Audience (relying party)"),
-                                 &rp),
-    GNUNET_GETOPT_option_flag ('D',
-                               "dump",
-                               gettext_noop ("List attributes for Ego"),
-                               &list),
-    GNUNET_GETOPT_option_string ('i',
-                                 "issue",
-                                 NULL,
-                                 gettext_noop ("Issue a ticket"),
-                                 &issue_attrs),
-    GNUNET_GETOPT_option_string ('C',
-                                 "consume",
-                                 NULL,
-                                 gettext_noop ("Consume a ticket"),
-                                 &consume_ticket),
-    GNUNET_GETOPT_option_string ('R',
-                                 "revoke",
-                                 NULL,
-                                 gettext_noop ("Revoke a ticket"),
-                                 &revoke_ticket),
-    GNUNET_GETOPT_option_string ('t',
-                                 "type",
-                                 NULL,
-                                 gettext_noop ("Type of attribute"),
-                                 &type_str),
-    GNUNET_GETOPT_option_relative_time ('E',
-                                        "expiration",
-                                        NULL,
-                                        gettext_noop ("Expiration interval of the attribute"),
-                                        &exp_interval),
-
-    GNUNET_GETOPT_OPTION_END
-  };
-  if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "ct",
-                                       "ct", options,
-                                       &run, NULL))
-    return 1;
-  else
-    return ret;
-}
diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c
deleted file mode 100644 (file)
index 4563fdf..0000000
+++ /dev/null
@@ -1,2786 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 GNUnet e.V.
-
-   GNUnet is free software: you can redistribute it and/or modify it
-   under the terms of the GNU Affero General Public License as published
-   by the Free Software Foundation, either version 3 of the License,
-   or (at your option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Affero General Public License for more details.
-  
-   You should have received a copy of the GNU Affero General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-   */
-/**
- * @author Martin Schanzenbach
- * @file src/identity-provider/gnunet-service-identity-provider.c
- * @brief Identity Token Service
- *
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_constants.h"
-#include "gnunet_protocols.h"
-#include "gnunet_identity_service.h"
-#include "gnunet_gnsrecord_lib.h"
-#include "gnunet_namestore_service.h"
-#include "gnunet_abe_lib.h"
-#include "gnunet_credential_service.h"
-#include "gnunet_statistics_service.h"
-#include "gnunet_gns_service.h"
-#include "gnunet_identity_provider_plugin.h"
-#include "gnunet_identity_attribute_lib.h"
-#include "gnunet_signatures.h"
-#include "identity_provider.h"
-
-/**
- * First pass state
- */
-#define STATE_INIT 0
-
-/**
- * Normal operation state
- */
-#define STATE_POST_INIT 1
-
-/**
- * Minimum interval between updates
- */
-#define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
-
-/**
- * Standard token expiration time
- */
-#define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
-
-/**
- * Identity handle
- */
-static struct GNUNET_IDENTITY_Handle *identity_handle;
-
-/**
- * Database handle
- */
-static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database;
-
-/**
- * Name of DB plugin
- */
-static char *db_lib_name;
-
-/**
- * Token expiration interval
- */
-static struct GNUNET_TIME_Relative token_expiration_interval;
-
-/**
- * Namestore handle
- */
-static struct GNUNET_NAMESTORE_Handle *ns_handle;
-
-/**
- * GNS handle
- */
-static struct GNUNET_GNS_Handle *gns_handle;
-
-/**
- * Credential handle
- */
-static struct GNUNET_CREDENTIAL_Handle *credential_handle;
-
-/**
- * Namestore qe
- */
-static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
-
-/**
- * Namestore iterator
- */
-static struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
-
-/**
- * Timeout task
- */
-static struct GNUNET_SCHEDULER_Task *timeout_task;
-
-/**
- * Update task
- */
-static struct GNUNET_SCHEDULER_Task *update_task;
-
-
-/**
- * Currently processed token
- */
-static struct IdentityToken *token;
-
-/**
- * Label for currently processed token
- */
-static char* label;
-
-/**
- * Scopes for processed token
- */
-static char* scopes;
-
-/**
- * Handle to the statistics service.
- */
-static struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Our configuration.
- */
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * An idp client
- */
-struct IdpClient;
-
-/**
- * A ticket iteration operation.
- */
-struct TicketIteration
-{
-  /**
-   * DLL
-   */
-  struct TicketIteration *next;
-
-  /**
-   * DLL
-   */
-  struct TicketIteration *prev;
-
-  /**
-   * Client which intiated this zone iteration
-   */
-  struct IdpClient *client;
-
-  /**
-   * Key of the identity we are iterating over.
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
-
-  /**
-   * Identity is audience
-   */
-  uint32_t is_audience;
-
-  /**
-   * The operation id fot the iteration in the response for the client
-   */
-  uint32_t r_id;
-
-  /**
-   * Offset of the iteration used to address next result of the 
-   * iteration in the store
-   *
-   * Initialy set to 0 in handle_iteration_start
-   * Incremented with by every call to handle_iteration_next
-   */
-  uint32_t offset;
-
-};
-
-
-
-/**
- * Callback after an ABE bootstrap
- *
- * @param cls closure
- * @param abe_key the ABE key that exists or was created
- */
-typedef void
-(*AbeBootstrapResult) (void *cls,
-                       struct GNUNET_ABE_AbeMasterKey *abe_key);
-
-
-struct AbeBootstrapHandle
-{
-  /**
-   * Function to call when finished
-   */
-  AbeBootstrapResult proc;
-
-  /**
-   * Callback closure
-   */
-  char *proc_cls;
-
-  /**
-   * Key of the zone we are iterating over.
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
-
-  /**
-   * Namestore Queue Entry
-   */
-  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
-
-  /**
-   * The issuer egos ABE master key
-   */
-  struct GNUNET_ABE_AbeMasterKey *abe_key;
-};
-
-/**
- * An attribute iteration operation.
- */
-struct AttributeIterator
-{
-  /**
-   * Next element in the DLL
-   */
-  struct AttributeIterator *next;
-
-  /**
-   * Previous element in the DLL
-   */
-  struct AttributeIterator *prev;
-
-  /**
-   * IDP client which intiated this zone iteration
-   */
-  struct IdpClient *client;
-
-  /**
-   * Key of the zone we are iterating over.
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
-
-  /**
-   * The issuer egos ABE master key
-   */
-  struct GNUNET_ABE_AbeMasterKey *abe_key;
-
-  /**
-   * Namestore iterator
-   */
-  struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
-
-  /**
-   * The operation id fot the zone iteration in the response for the client
-   */
-  uint32_t request_id;
-
-};
-
-
-
-/**
- * An idp client
- */
-struct IdpClient
-{
-
-  /**
-   * The client
-   */
-  struct GNUNET_SERVICE_Client *client;
-
-  /**
-   * Message queue for transmission to @e client
-   */
-  struct GNUNET_MQ_Handle *mq;
-  
-  /**
-   * Head of the DLL of
-   * Attribute iteration operations in 
-   * progress initiated by this client
-   */
-  struct AttributeIterator *attr_iter_head;
-
-  /**
-   * Tail of the DLL of
-   * Attribute iteration operations 
-   * in progress initiated by this client
-   */
-  struct AttributeIterator *attr_iter_tail;
-
-  /**
-   * Head of DLL of ticket iteration ops
-   */
-  struct TicketIteration *ticket_iter_head;
-
-  /**
-   * Tail of DLL of ticket iteration ops
-   */
-  struct TicketIteration *ticket_iter_tail;
-
-  /**
-   * Head of DLL of ticket revocation ops
-   */
-  struct TicketRevocationHandle *revoke_op_head;
-
-  /**
-   * Tail of DLL of ticket revocation ops
-   */
-  struct TicketRevocationHandle *revoke_op_tail;
-
-  /**
-   * Head of DLL of ticket issue ops
-   */
-  struct TicketIssueHandle *issue_op_head;
-
-  /**
-   * Tail of DLL of ticket issue ops
-   */
-  struct TicketIssueHandle *issue_op_tail;
-
-  /**
-   * Head of DLL of ticket consume ops
-   */
-  struct ConsumeTicketHandle *consume_op_head;
-
-  /**
-   * Tail of DLL of ticket consume ops
-   */
-  struct ConsumeTicketHandle *consume_op_tail;
-
-  /**
-   * Head of DLL of attribute store ops
-   */
-  struct AttributeStoreHandle *store_op_head;
-
-  /**
-   * Tail of DLL of attribute store ops
-   */
-  struct AttributeStoreHandle *store_op_tail;
-
-};
-
-struct AttributeStoreHandle
-{
-  /**
-   * DLL
-   */
-  struct AttributeStoreHandle *next;
-
-  /**
-   * DLL
-   */
-  struct AttributeStoreHandle *prev;
-
-  /**
-   * Client connection
-   */
-  struct IdpClient *client;
-
-  /**
-   * Identity
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
-
-  /**
-   * Identity pubkey
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
-
-  /**
-   * The issuer egos ABE master key
-   */
-  struct GNUNET_ABE_AbeMasterKey *abe_key;
-
-  /**
-   * QueueEntry
-   */
-  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
-
-  /**
-   * The attribute to store
-   */
-  struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
-
-  /**
-   * The attribute expiration interval
-   */
-  struct GNUNET_TIME_Relative exp;
-
-  /**
-   * request id
-   */
-  uint32_t r_id;
-};
-
-
-/* Prototype */
-struct ParallelLookup;
-
-struct ConsumeTicketHandle
-{
-  /**
-   * DLL
-   */
-  struct ConsumeTicketHandle *next;
-
-  /**
-   * DLL
-   */
-  struct ConsumeTicketHandle *prev;
-
-  /**
-   * Client connection
-   */
-  struct IdpClient *client;
-
-  /**
-   * Ticket
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
-
-  /**
-   * LookupRequest
-   */
-  struct GNUNET_GNS_LookupRequest *lookup_request;
-
-  /**
-   * Audience Key
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
-
-  /**
-   * Audience Key
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
-
-  /**
-   * Lookup DLL
-   */
-  struct ParallelLookup *parallel_lookups_head;
-
-  /**
-   * Lookup DLL
-   */
-  struct ParallelLookup *parallel_lookups_tail;
-  
-  /**
-   * Kill task
-   */
-  struct GNUNET_SCHEDULER_Task *kill_task;
-
-  /**
-   * The ABE key
-   */
-  struct GNUNET_ABE_AbeKey *key;
-
-  /**
-   * Attributes
-   */
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
-  
-  /**
-   * Lookup time
-   */
-  struct GNUNET_TIME_Absolute lookup_start_time;
-  /**
-   * request id
-   */
-  uint32_t r_id;
-};
-
-/**
- * Handle for a parallel GNS lookup job
- */
-struct ParallelLookup
-{
-  /* DLL */
-  struct ParallelLookup *next;
-
-  /* DLL */
-  struct ParallelLookup *prev;
-
-  /* The GNS request */
-  struct GNUNET_GNS_LookupRequest *lookup_request;
-
-  /* The handle the return to */
-  struct ConsumeTicketHandle *handle;
-
-  /**
-   * Lookup time
-   */
-  struct GNUNET_TIME_Absolute lookup_start_time;
-
-  /* The label to look up */
-  char *label;
-};
-
-/**
- * Ticket revocation request handle
- */
-struct TicketRevocationHandle
-{
-  /**
-   * DLL
-   */
-  struct TicketRevocationHandle *prev;
-
-  /**
-   * DLL
-   */
-  struct TicketRevocationHandle *next;
-
-  /**
-   * Client connection
-   */
-  struct IdpClient *client;
-
-  /**
-   * Attributes to reissue
-   */
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
-
-  /**
-   * Attributes to revoke
-   */
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *rvk_attrs;
-
-  /**
-   * Issuer Key
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
-
-  /**
-   * Ticket to issue
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
-
-  /**
-   * QueueEntry
-   */
-  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
-
-  /**
-   * Namestore iterator
-   */
-  struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
-
-  /**
-   * The ABE master key
-   */
-  struct GNUNET_ABE_AbeMasterKey *abe_key;
-
-  /**
-   * Offset
-   */
-  uint32_t offset;
-
-  /**
-   * request id
-   */
-  uint32_t r_id;
-};
-
-
-
-/**
- * Ticket issue request handle
- */
-struct TicketIssueHandle
-{
-  /**
-   * DLL
-   */
-  struct TicketIssueHandle *prev;
-
-  /**
-   * DLL
-   */
-  struct TicketIssueHandle *next;
-
-  /**
-   * Client connection
-   */
-  struct IdpClient *client;
-
-  /**
-   * Attributes to issue
-   */
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
-
-  /**
-   * Issuer Key
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
-
-  /**
-   * Ticket to issue
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
-
-  /**
-   * QueueEntry
-   */
-  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
-
-  /**
-   * request id
-   */
-  uint32_t r_id;
-};
-
-
-/**
- * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
- *
- */
-struct EgoEntry
-{
-  /**
-   * DLL
-   */
-  struct EgoEntry *next;
-
-  /**
-   * DLL
-   */
-  struct EgoEntry *prev;
-
-  /**
-   * Ego handle
-   */
-  struct GNUNET_IDENTITY_Ego *ego;
-
-  /**
-   * Attribute map. Contains the attributes as json_t
-   */
-  struct GNUNET_CONTAINER_MultiHashMap *attr_map;
-
-};
-
-/**
- * Cleanup task
- */
-static void
-cleanup()
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Cleaning up\n");
-
-  if (NULL != stats)
-  {
-    GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
-    stats = NULL;
-  }
-  GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
-                                              TKT_database)); 
-  GNUNET_free (db_lib_name);
-  db_lib_name = NULL;
-  if (NULL != timeout_task)
-    GNUNET_SCHEDULER_cancel (timeout_task);
-  if (NULL != update_task)
-    GNUNET_SCHEDULER_cancel (update_task);
-  if (NULL != identity_handle)
-    GNUNET_IDENTITY_disconnect (identity_handle);
-  if (NULL != gns_handle)
-    GNUNET_GNS_disconnect (gns_handle);
-  if (NULL != credential_handle)
-    GNUNET_CREDENTIAL_disconnect (credential_handle);
-  if (NULL != ns_it)
-    GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
-  if (NULL != ns_qe)
-    GNUNET_NAMESTORE_cancel (ns_qe);
-  if (NULL != ns_handle)
-    GNUNET_NAMESTORE_disconnect (ns_handle);
-  GNUNET_free_non_null (token);
-  GNUNET_free_non_null (label);
-
-}
-
-/**
- * Shutdown task
- *
- * @param cls NULL
- */
-static void
-do_shutdown (void *cls)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Shutting down...\n");
-  cleanup();
-}
-
-/**
- * Finished storing newly bootstrapped ABE key
- */
-static void
-bootstrap_store_cont (void *cls,
-                      int32_t success,
-                      const char *emsg)
-{
-  struct AbeBootstrapHandle *abh = cls;
-  if (GNUNET_SYSERR == success)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to bootstrap ABE master %s\n",
-                emsg);
-    abh->proc (abh->proc_cls, NULL);
-    GNUNET_free (abh->abe_key);
-    GNUNET_free (abh);
-    return;
-  }
-  abh->proc (abh->proc_cls, abh->abe_key);
-  GNUNET_free (abh);
-}
-
-/**
- * Generates and stores a new ABE key
- */
-static void
-bootstrap_store_task (void *cls)
-{
-  struct AbeBootstrapHandle *abh = cls;
-  struct GNUNET_GNSRECORD_Data rd[1];
-  char *key;
-
-  rd[0].data_size = GNUNET_ABE_cpabe_serialize_master_key (abh->abe_key,
-                                                              (void**)&key);
-  rd[0].data = key;
-  rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
-  rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
-  rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
-  abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
-                                               &abh->identity,
-                                               "+",
-                                               1,
-                                               rd,
-                                               &bootstrap_store_cont,
-                                               abh);
-  GNUNET_free (key);
-}
-
-/**
- * Error checking for ABE master
- */
-static void
-bootstrap_abe_error (void *cls)
-{
-  struct AbeBootstrapHandle *abh = cls;
-  abh->proc (abh->proc_cls, NULL);
-  GNUNET_free (abh);
-}
-
-
-/**
- * Handle ABE lookup in namestore
- */
-static void
-bootstrap_abe_result (void *cls,
-                      const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                      const char *label,
-                      unsigned int rd_count,
-                      const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct AbeBootstrapHandle *abh = cls;
-  struct GNUNET_ABE_AbeMasterKey *abe_key;
-
-  for (uint32_t i=0;i<rd_count;i++) {
-    if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
-      continue;
-    abe_key = GNUNET_ABE_cpabe_deserialize_master_key (rd[i].data,
-                                                          rd[i].data_size);
-    abh->proc (abh->proc_cls, abe_key);
-    GNUNET_free (abh);
-    return;
-  }
-
-  //No ABE master found, bootstrapping...
-  abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
-  GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
-}
-
-/**
- * Bootstrap ABE master if it does not yet exists.
- * Will call the AbeBootstrapResult processor when done.
- * will always recreate the ABE key of GNUNET_YES == recreate
- */
-static void
-bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
-               AbeBootstrapResult proc,
-               void* cls,
-               int recreate)
-{
-  struct AbeBootstrapHandle *abh;
-
-  abh = GNUNET_new (struct AbeBootstrapHandle);
-  abh->proc = proc;
-  abh->proc_cls = cls;
-  abh->identity = *identity;
-  if (GNUNET_YES == recreate)
-  {
-    abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
-    GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
-  } else {
-    abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
-                                                  identity,
-                                                  "+",
-                                                  &bootstrap_abe_error,
-                                                  abh,
-                                                  &bootstrap_abe_result,
-                                                  abh);
-  }
-}
-
-
-
-static int
-create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
-                         struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
-                         struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
-{
-  struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
-
-  GNUNET_CRYPTO_hash_to_enc (new_key_hash,
-                             &new_key_hash_str);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
-  static const char ctx_key[] = "gnuid-aes-ctx-key";
-  GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
-                     new_key_hash, sizeof (struct GNUNET_HashCode),
-                     ctx_key, strlen (ctx_key),
-                     NULL, 0);
-  static const char ctx_iv[] = "gnuid-aes-ctx-iv";
-  GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
-                     new_key_hash, sizeof (struct GNUNET_HashCode),
-                     ctx_iv, strlen (ctx_iv),
-                     NULL, 0);
-  return GNUNET_OK;
-}
-
-/**
- * Cleanup ticket consume handle
- * @param handle the handle to clean up
- */
-static void
-cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
-{
-  if (NULL != handle->attrs)
-    GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
-  if (NULL != handle->ns_qe)
-    GNUNET_NAMESTORE_cancel (handle->ns_qe);
-  GNUNET_free (handle);
-}
-
-
-static void
-send_ticket_result (struct IdpClient *client,
-                    uint32_t r_id,
-                    const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                    const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
-{
-  struct TicketResultMessage *irm;
-  struct GNUNET_MQ_Envelope *env;
-  struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
-
-  /* store ticket in DB */
-  if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
-                                               ticket,
-                                               attrs))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unable to store ticket after issue\n");
-    GNUNET_break (0);
-  }
-
-  env = GNUNET_MQ_msg_extra (irm,
-                             sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
-                             GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
-  ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
-  *ticket_buf = *ticket;
-  irm->id = htonl (r_id);
-  GNUNET_MQ_send (client->mq,
-                  env);
-}
-
-static void
-store_ticket_issue_cont (void *cls,
-                         int32_t success,
-                         const char *emsg)
-{
-  struct TicketIssueHandle *handle = cls;
-
-  handle->ns_qe = NULL;
-  GNUNET_CONTAINER_DLL_remove (handle->client->issue_op_head,
-                               handle->client->issue_op_tail,
-                               handle);
-  if (GNUNET_SYSERR == success)
-  {
-    cleanup_ticket_issue_handle (handle);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
-                "Unknown Error\n");
-    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
-    return;
-  }
-  send_ticket_result (handle->client,
-                      handle->r_id,
-                      &handle->ticket,
-                      handle->attrs);
-  cleanup_ticket_issue_handle (handle);
-}
-
-
-
-int
-serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                        const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
-                        const struct GNUNET_ABE_AbeKey *rp_key,
-                        struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
-                        char **result)
-{
-  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-  char *enc_keyinfo;
-  char *serialized_key;
-  char *buf;
-  char *write_ptr;
-  char attrs_str_len;
-  ssize_t size;
-
-  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
-  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
-  struct GNUNET_HashCode new_key_hash;
-  ssize_t enc_size;
-
-  size = GNUNET_ABE_cpabe_serialize_key (rp_key,
-                                         (void**)&serialized_key);
-  attrs_str_len = 0;
-  for (le = attrs->list_head; NULL != le; le = le->next) {
-    attrs_str_len += strlen (le->claim->name) + 1;
-  }
-  buf = GNUNET_malloc (attrs_str_len + size);
-  write_ptr = buf;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Writing attributes\n");
-  for (le = attrs->list_head; NULL != le; le = le->next) {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "%s\n", le->claim->name);
-
-
-    GNUNET_memcpy (write_ptr,
-                   le->claim->name,
-                   strlen (le->claim->name));
-    write_ptr[strlen (le->claim->name)] = ',';
-    write_ptr += strlen (le->claim->name) + 1;
-  }
-  write_ptr--;
-  write_ptr[0] = '\0'; //replace last , with a 0-terminator
-  write_ptr++;
-  GNUNET_memcpy (write_ptr,
-                 serialized_key,
-                 size);
-  GNUNET_free (serialized_key);
-  // ECDH keypair E = eG
-  *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
-  GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
-                                      &ecdh_pubkey);
-  enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
-  // Derived key K = H(eB)
-  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
-                                                        &ticket->audience,
-                                                        &new_key_hash));
-  create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
-  enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
-                                              size + attrs_str_len,
-                                              &skey, &iv,
-                                              enc_keyinfo);
-  *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
-                           enc_size);
-  GNUNET_memcpy (*result,
-                 &ecdh_pubkey,
-                 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
-  GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
-                 enc_keyinfo,
-                 enc_size);
-  GNUNET_free (enc_keyinfo);
-  GNUNET_free (buf);
-  return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
-}
-
-
-
-static void
-issue_ticket_after_abe_bootstrap (void *cls,
-                                  struct GNUNET_ABE_AbeMasterKey *abe_key)
-{
-  struct TicketIssueHandle *ih = cls;
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
-  struct GNUNET_GNSRECORD_Data code_record[1];
-  struct GNUNET_ABE_AbeKey *rp_key;
-  char *code_record_data;
-  char **attrs;
-  char *label;
-  char *policy;
-  int attrs_len;
-  uint32_t i;
-  size_t code_record_len;
-
-  //Create new ABE key for RP
-  attrs_len = 0;
-  for (le = ih->attrs->list_head; NULL != le; le = le->next)
-    attrs_len++;
-  attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
-  i = 0;
-  for (le = ih->attrs->list_head; NULL != le; le = le->next) {
-    GNUNET_asprintf (&policy, "%s_%lu",
-                     le->claim->name,
-                     le->claim->version);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Adding attribute to key: %s\n",
-                policy);
-    attrs[i] = policy;
-    i++;
-  }
-  attrs[i] = NULL;
-  rp_key = GNUNET_ABE_cpabe_create_key (abe_key,
-                                        attrs);
-
-  //TODO review this wireformat
-  code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
-                                            ih->attrs,
-                                            rp_key,
-                                            &ecdhe_privkey,
-                                            &code_record_data);
-  code_record[0].data = code_record_data;
-  code_record[0].data_size = code_record_len;
-  code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
-  code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
-  code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
-
-  label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
-                                               sizeof (uint64_t));
-  //Publish record
-  ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
-                                              &ih->identity,
-                                              label,
-                                              1,
-                                              code_record,
-                                              &store_ticket_issue_cont,
-                                              ih);
-  //for (; i > 0; i--)
-  //  GNUNET_free (attrs[i-1]);
-  GNUNET_free (ecdhe_privkey);
-  GNUNET_free (label);
-  GNUNET_free (attrs);
-  GNUNET_free (code_record_data);
-  GNUNET_ABE_cpabe_delete_key (rp_key,
-                               GNUNET_YES);
-  GNUNET_ABE_cpabe_delete_master_key (abe_key);
-}
-
-
-static int
-check_issue_ticket_message(void *cls,
-                           const struct IssueTicketMessage *im)
-{
-  uint16_t size;
-
-  size = ntohs (im->header.size);
-  if (size <= sizeof (struct IssueTicketMessage))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-
-static void
-handle_issue_ticket_message (void *cls,
-                             const struct IssueTicketMessage *im)
-{
-  struct TicketIssueHandle *ih;
-  struct IdpClient *idp = cls;
-  size_t attrs_len;
-
-  ih = GNUNET_new (struct TicketIssueHandle);
-  attrs_len = ntohs (im->attr_len);
-  ih->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&im[1], attrs_len);
-  ih->r_id = ntohl (im->id);
-  ih->client = idp;
-  ih->identity = im->identity;
-  GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
-                                      &ih->ticket.identity);
-  ih->ticket.audience = im->rp;
-  ih->ticket.rnd =
-    GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
-                              UINT64_MAX);
-  GNUNET_CONTAINER_DLL_insert (idp->issue_op_head,
-                               idp->issue_op_tail,
-                               ih);
-  bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
-  GNUNET_SERVICE_client_continue (idp->client);
-
-}
-
-/**********************************************************
- * Revocation
- **********************************************************/
-
-/**
- * Cleanup revoke handle
- *
- * @param rh the ticket revocation handle
- */
-static void
-cleanup_revoke_ticket_handle (struct TicketRevocationHandle *rh)
-{
-  if (NULL != rh->attrs)
-    GNUNET_IDENTITY_ATTRIBUTE_list_destroy (rh->attrs);
-  if (NULL != rh->rvk_attrs)
-    GNUNET_IDENTITY_ATTRIBUTE_list_destroy (rh->rvk_attrs);
-  if (NULL != rh->abe_key)
-    GNUNET_ABE_cpabe_delete_master_key (rh->abe_key);
-  if (NULL != rh->ns_qe)
-    GNUNET_NAMESTORE_cancel (rh->ns_qe);
-  if (NULL != rh->ns_it)
-    GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
-  GNUNET_free (rh);
-}
-
-
-/**
- * Send revocation result
- *
- * @param rh ticket revocation handle
- * @param success GNUNET_OK if successful result
- */
-static void
-send_revocation_finished (struct TicketRevocationHandle *rh,
-                          uint32_t success)
-{
-  struct GNUNET_MQ_Envelope *env;
-  struct RevokeTicketResultMessage *trm;
-  
-  GNUNET_break(TKT_database->delete_ticket (TKT_database->cls,
-                                            &rh->ticket));
-
-  env = GNUNET_MQ_msg (trm,
-                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT);
-  trm->id = htonl (rh->r_id);
-  trm->success = htonl (success);
-  GNUNET_MQ_send (rh->client->mq,
-                  env);
-  GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head,
-                               rh->client->revoke_op_tail,
-                               rh);
-}
-
-
-/**
- * Process ticket from database
- *
- * @param cls struct TicketIterationProcResult
- * @param ticket the ticket
- * @param attrs the attributes
- */
-static void
-ticket_reissue_proc (void *cls,
-                     const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                     const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
-
-static void
-revocation_reissue_tickets (struct TicketRevocationHandle *rh);
-
-
-static void reissue_next (void *cls)
-{
-  struct TicketRevocationHandle *rh = cls;
-  revocation_reissue_tickets (rh);
-}
-
-
-static void
-reissue_ticket_cont (void *cls,
-                     int32_t success,
-                     const char *emsg)
-{
-  struct TicketRevocationHandle *rh = cls;
-
-  rh->ns_qe = NULL;
-  if (GNUNET_SYSERR == success)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
-                "Unknown Error\n");
-    send_revocation_finished (rh, GNUNET_SYSERR);
-    cleanup_revoke_ticket_handle (rh);
-    return;
-  }
-  rh->offset++;
-  GNUNET_SCHEDULER_add_now (&reissue_next, rh);
-}
-
-
-/**
- * Process ticket from database
- *
- * @param cls struct TicketIterationProcResult
- * @param ticket the ticket
- * @param attrs the attributes
- */
-static void
-ticket_reissue_proc (void *cls,
-                     const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                     const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
-{
-  struct TicketRevocationHandle *rh = cls;
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le_rollover;
-  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
-  struct GNUNET_GNSRECORD_Data code_record[1];
-  struct GNUNET_ABE_AbeKey *rp_key;
-  char *code_record_data;
-  char **attr_arr;
-  char *label;
-  char *policy;
-  int attrs_len;
-  uint32_t i;
-  int reissue_ticket;
-  size_t code_record_len;
-
-
-  if (NULL == ticket)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Iteration done\n");
-    return;
-  }
-
-  if (0 == memcmp (&ticket->audience,
-                   &rh->ticket.audience,
-                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Do not reissue for this identity.!\n");
-    label = GNUNET_STRINGS_data_to_string_alloc (&rh->ticket.rnd,
-                                                 sizeof (uint64_t));
-    //Delete record
-    rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
-                                                &rh->identity,
-                                                label,
-                                                0,
-                                                NULL,
-                                                &reissue_ticket_cont,
-                                                rh);
-
-    GNUNET_free (label);
-    return;
-  }
-
-  /* 
-   * Check if any attribute of this ticket intersects with a rollover attribute
-   */
-  reissue_ticket = GNUNET_NO;
-  for (le = attrs->list_head; NULL != le; le = le->next)
-  {
-    for (le_rollover = rh->rvk_attrs->list_head;
-         NULL != le_rollover;
-         le_rollover = le_rollover->next)
-    {
-      if (0 == strcmp (le_rollover->claim->name,
-                       le->claim->name))
-      {
-        reissue_ticket = GNUNET_YES;
-        le->claim->version = le_rollover->claim->version;
-      }
-    }
-  }
-
-  if (GNUNET_NO == reissue_ticket)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Skipping ticket.\n");
-
-    rh->offset++;
-    GNUNET_SCHEDULER_add_now (&reissue_next, rh);
-
-
-    return;
-  }
-
-  //Create new ABE key for RP
-  attrs_len = 0;
-
-  /* If this is the RP we want to revoke attributes of, the do so */
-
-  for (le = attrs->list_head; NULL != le; le = le->next)
-    attrs_len++;
-  attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
-  i = 0;
-  for (le = attrs->list_head; NULL != le; le = le->next) {
-    GNUNET_asprintf (&policy, "%s_%lu",
-                     le->claim->name,
-                     le->claim->version);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Recreating key with %s\n", policy);
-    attr_arr[i] = policy;
-    i++;
-  }
-  attr_arr[i] = NULL;
-  rp_key = GNUNET_ABE_cpabe_create_key (rh->abe_key,
-                                        attr_arr);
-
-  //TODO review this wireformat
-  code_record_len = serialize_abe_keyinfo2 (ticket,
-                                            attrs,
-                                            rp_key,
-                                            &ecdhe_privkey,
-                                            &code_record_data);
-  code_record[0].data = code_record_data;
-  code_record[0].data_size = code_record_len;
-  code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
-  code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
-  code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
-
-  label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
-                                               sizeof (uint64_t));
-  //Publish record
-  rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
-                                              &rh->identity,
-                                              label,
-                                              1,
-                                              code_record,
-                                              &reissue_ticket_cont,
-                                              rh);
-  //for (; i > 0; i--)
-  //  GNUNET_free (attr_arr[i-1]);
-  GNUNET_free (ecdhe_privkey);
-  GNUNET_free (label);
-  GNUNET_free (attr_arr);
-  GNUNET_free (code_record_data);
-  GNUNET_ABE_cpabe_delete_key (rp_key, GNUNET_YES);
-}
-
-
-/* Prototype for below function */
-static void
-attr_reenc_cont (void *cls,
-                 int32_t success,
-                 const char *emsg);
-
-static void
-revocation_reissue_tickets (struct TicketRevocationHandle *rh)
-{
-  int ret;
-  /* Done, issue new keys */
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Revocation Phase III: Reissuing Tickets\n");
-  if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
-                                                             &rh->ticket.identity,
-                                                             GNUNET_NO,
-                                                             rh->offset,
-                                                             &ticket_reissue_proc,
-                                                             rh)))
-  {
-    GNUNET_break (0);
-  }
-  if (GNUNET_NO == ret)
-  {
-    send_revocation_finished (rh, GNUNET_OK);
-    cleanup_revoke_ticket_handle (rh);
-    return;
-  }
-}
-
-/**
- * Failed to check for attribute
- */
-static void
-check_attr_error (void *cls)
-{
-  struct TicketRevocationHandle *rh = cls;
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Unable to check for existing attribute\n");
-  rh->ns_qe = NULL;
-  send_revocation_finished (rh, GNUNET_SYSERR);
-  cleanup_revoke_ticket_handle (rh);
-}
-
-
-/**
- * Revoke next attribte by reencryption with
- * new ABE master
- */
-static void
-reenc_next_attribute (void *cls);
-
-/**
- * Check for existing attribute and overwrite
- */
-static void
-check_attr_cb (void *cls,
-               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-               const char *label,
-               unsigned int rd_count,
-               const struct GNUNET_GNSRECORD_Data *rd_old)
-{
-  struct TicketRevocationHandle *rh = cls;
-  struct GNUNET_GNSRECORD_Data rd[1];
-  char* buf;
-  char* enc_buf;
-  size_t enc_size;
-  char* rd_buf;
-  size_t buf_size;
-  char* policy;
-  uint32_t attr_ver;
-
-  rh->ns_qe = NULL;
-  if (1 != rd_count) {
-    GNUNET_SCHEDULER_add_now (&reenc_next_attribute,
-                              rh);
-    return;
-  }
-
-  buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim);
-  buf = GNUNET_malloc (buf_size);
-  GNUNET_IDENTITY_ATTRIBUTE_serialize (rh->attrs->list_head->claim,
-                                       buf);
-  rh->attrs->list_head->claim->version++;
-  GNUNET_asprintf (&policy, "%s_%lu",
-                   rh->attrs->list_head->claim->name,
-                   rh->attrs->list_head->claim->version);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Encrypting with policy %s\n", policy);
-  /**
-   * Encrypt the attribute value and store in namestore
-   */
-  enc_size = GNUNET_ABE_cpabe_encrypt (buf,
-                                       buf_size,
-                                       policy, //Policy
-                                       rh->abe_key,
-                                       (void**)&enc_buf);
-  GNUNET_free (buf);
-  if (GNUNET_SYSERR == enc_size)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unable to re-encrypt with policy %s\n",
-                policy);
-    GNUNET_free (policy);
-    send_revocation_finished (rh, GNUNET_SYSERR);
-    cleanup_revoke_ticket_handle (rh);
-    return;
-  }
-  GNUNET_free (policy);
-
-  rd[0].data_size = enc_size + sizeof (uint32_t);
-  rd_buf = GNUNET_malloc (rd[0].data_size);
-  attr_ver = htonl (rh->attrs->list_head->claim->version);
-  GNUNET_memcpy (rd_buf,
-                 &attr_ver,
-                 sizeof (uint32_t));
-  GNUNET_memcpy (rd_buf+sizeof (uint32_t),
-                 enc_buf,
-                 enc_size);
-  rd[0].data = rd_buf;
-  rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
-  rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
-  rd[0].expiration_time = rd_old[0].expiration_time;
-  rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
-                                              &rh->identity,
-                                              rh->attrs->list_head->claim->name,
-                                              1,
-                                              rd,
-                                              &attr_reenc_cont,
-                                              rh);
-  GNUNET_free (enc_buf);
-  GNUNET_free (rd_buf);
-}
-
-
-/**
- * Revoke next attribte by reencryption with
- * new ABE master
- */
-static void
-reenc_next_attribute (void *cls)
-{
-  struct TicketRevocationHandle *rh = cls;
-  if (NULL == rh->attrs->list_head)
-  {
-    revocation_reissue_tickets (rh);
-    return;
-  }
-  /* First check if attribute still exists */
-  rh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
-                                               &rh->identity,
-                                               rh->attrs->list_head->claim->name,
-                                               &check_attr_error,
-                                               rh,
-                                               &check_attr_cb,
-                                               rh);
-}
-
-
-/**
- * Namestore callback after revoked attribute
- * is stored
- */
-static void
-attr_reenc_cont (void *cls,
-                 int32_t success,
-                 const char *emsg)
-{
-  struct TicketRevocationHandle *rh = cls;
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-
-  rh->ns_qe = NULL;
-  if (GNUNET_SYSERR == success)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to reencrypt attribute %s\n",
-                emsg);
-    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
-    return;
-  }
-  if (NULL == rh->attrs->list_head)
-  {
-    revocation_reissue_tickets (rh);
-    return;
-  }
-  le = rh->attrs->list_head;
-  GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
-                               rh->attrs->list_tail,
-                               le);
-  GNUNET_assert (NULL != rh->rvk_attrs);
-  GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
-                               rh->rvk_attrs->list_tail,
-                               le);
-
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Re-encrypting next attribute\n");
-  reenc_next_attribute (rh);
-}
-
-
-static void
-process_attributes_to_update (void *cls,
-                              const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                              const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
-{
-  struct TicketRevocationHandle *rh = cls;
-
-  rh->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_dup (attrs);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Revocation Phase I: Collecting attributes\n");
-  /* Reencrypt all attributes with new key */
-  if (NULL == rh->attrs->list_head)
-  {
-    /* No attributes to reencrypt */
-    send_revocation_finished (rh, GNUNET_OK);
-    cleanup_revoke_ticket_handle (rh);
-    return;
-  } else {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Revocation Phase II: Re-encrypting attributes\n");
-    reenc_next_attribute (rh);
-  }
-
-}
-
-
-
-static void
-get_ticket_after_abe_bootstrap (void *cls,
-                                struct GNUNET_ABE_AbeMasterKey *abe_key)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Finished ABE bootstrap\n");
-  struct TicketRevocationHandle *rh = cls;
-  rh->abe_key = abe_key;
-  TKT_database->get_ticket_attributes (TKT_database->cls,
-                                       &rh->ticket,
-                                       &process_attributes_to_update,
-                                       rh);
-}
-
-static int
-check_revoke_ticket_message(void *cls,
-                            const struct RevokeTicketMessage *im)
-{
-  uint16_t size;
-
-  size = ntohs (im->header.size);
-  if (size <= sizeof (struct RevokeTicketMessage))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-static void
-handle_revoke_ticket_message (void *cls,
-                              const struct RevokeTicketMessage *rm)
-{
-  struct TicketRevocationHandle *rh;
-  struct IdpClient *idp = cls;
-  struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
-
-  rh = GNUNET_new (struct TicketRevocationHandle);
-  ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1];
-  rh->rvk_attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
-  rh->ticket = *ticket;
-  rh->r_id = ntohl (rm->id);
-  rh->client = idp;
-  rh->identity = rm->identity;
-  GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
-                                      &rh->ticket.identity);
-  GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head,
-                               idp->revoke_op_tail,
-                               rh);
-  bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO);
-  GNUNET_SERVICE_client_continue (idp->client);
-
-}
-
-/**
- * Cleanup ticket consume handle
- * @param handle the handle to clean up
- */
-static void
-cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
-{
-  struct ParallelLookup *lu;  
-  struct ParallelLookup *tmp;
-  if (NULL != handle->lookup_request)
-    GNUNET_GNS_lookup_cancel (handle->lookup_request);
-  for (lu = handle->parallel_lookups_head;
-       NULL != lu;) {
-    GNUNET_GNS_lookup_cancel (lu->lookup_request);
-    GNUNET_free (lu->label);
-    tmp = lu->next;
-    GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
-                                 handle->parallel_lookups_tail,
-                                 lu);
-    GNUNET_free (lu);
-    lu = tmp;
-  }
-
-  if (NULL != handle->key)
-    GNUNET_ABE_cpabe_delete_key (handle->key,
-                                 GNUNET_YES);
-  if (NULL != handle->attrs)
-    GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
-  GNUNET_free (handle);
-}
-
-
-
-static int
-check_consume_ticket_message(void *cls,
-                             const struct ConsumeTicketMessage *cm)
-{
-  uint16_t size;
-
-  size = ntohs (cm->header.size);
-  if (size <= sizeof (struct ConsumeTicketMessage))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-static void
-process_parallel_lookup2 (void *cls, uint32_t rd_count,
-                          const struct GNUNET_GNSRECORD_Data *rd)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Parallel lookup finished (count=%u)\n", rd_count);
-  struct ParallelLookup *parallel_lookup = cls;
-  struct ConsumeTicketHandle *handle = parallel_lookup->handle;
-  struct ConsumeTicketResultMessage *crm;
-  struct GNUNET_MQ_Envelope *env;
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *attr_le;
-  struct GNUNET_TIME_Absolute decrypt_duration;
-  char *data;
-  char *data_tmp;
-  ssize_t attr_len;
-  size_t attrs_len;
-
-  GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
-                               handle->parallel_lookups_tail,
-                               parallel_lookup);
-  GNUNET_free (parallel_lookup->label);
-
-  GNUNET_STATISTICS_update (stats,
-                            "attribute_lookup_time_total",
-                            GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us,
-                            GNUNET_YES);
-  GNUNET_STATISTICS_update (stats,
-                            "attribute_lookups_count",
-                            1,
-                            GNUNET_YES);
-
-
-  GNUNET_free (parallel_lookup);
-  if (1 != rd_count)
-    GNUNET_break(0);//TODO
-  if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
-  {
-    decrypt_duration = GNUNET_TIME_absolute_get ();
-    attr_len = GNUNET_ABE_cpabe_decrypt (rd->data + sizeof (uint32_t),
-                                         rd->data_size - sizeof (uint32_t),
-                                         handle->key,
-                                         (void**)&data);
-    if (GNUNET_SYSERR != attr_len) 
-    {
-      GNUNET_STATISTICS_update (stats,
-                                "abe_decrypt_time_total",
-                                GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us,
-                                GNUNET_YES);
-      GNUNET_STATISTICS_update (stats,
-                                "abe_decrypt_count",
-                                1,
-                                GNUNET_YES);
-
-      attr_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
-      attr_le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (data,
-                                                              attr_len);
-      attr_le->claim->version = ntohl(*(uint32_t*)rd->data);
-      GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
-                                   handle->attrs->list_tail,
-                                   attr_le);
-      GNUNET_free (data);
-    }
-  }
-  if (NULL != handle->parallel_lookups_head)
-    return; //Wait for more
-  /* Else we are done */
-
-  /* Store ticket in DB */
-  if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
-                                               &handle->ticket,
-                                               handle->attrs))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unable to store ticket after consume\n");
-    GNUNET_break (0);
-  }
-
-  GNUNET_SCHEDULER_cancel (handle->kill_task);
-  attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (handle->attrs);
-  env = GNUNET_MQ_msg_extra (crm,
-                             attrs_len,
-                             GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
-  crm->id = htonl (handle->r_id);
-  crm->attrs_len = htons (attrs_len);
-  crm->identity = handle->ticket.identity;
-  data_tmp = (char *) &crm[1];
-  GNUNET_IDENTITY_ATTRIBUTE_list_serialize (handle->attrs,
-                                            data_tmp);
-  GNUNET_MQ_send (handle->client->mq, env);
-  GNUNET_CONTAINER_DLL_remove (handle->client->consume_op_head,
-                               handle->client->consume_op_tail,
-                               handle);
-  cleanup_consume_ticket_handle (handle);
-}
-
-void
-abort_parallel_lookups2 (void *cls)
-{
-  struct ConsumeTicketHandle *handle = cls;
-  struct ParallelLookup *lu;
-  struct ParallelLookup *tmp;
-  struct AttributeResultMessage *arm;
-  struct GNUNET_MQ_Envelope *env;
-
-  handle->kill_task = NULL;
-  for (lu = handle->parallel_lookups_head;
-       NULL != lu;) {
-    GNUNET_GNS_lookup_cancel (lu->lookup_request);
-    GNUNET_free (lu->label);
-    tmp = lu->next;
-    GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
-                                 handle->parallel_lookups_tail,
-                                 lu);
-    GNUNET_free (lu);
-    lu = tmp;
-  }
-  env = GNUNET_MQ_msg (arm,
-                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
-  arm->id = htonl (handle->r_id);
-  arm->attr_len = htons (0);
-  GNUNET_MQ_send (handle->client->mq, env);
-
-}
-
-
-static void
-process_consume_abe_key (void *cls, uint32_t rd_count,
-                         const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct ConsumeTicketHandle *handle = cls;
-  struct GNUNET_HashCode new_key_hash;
-  struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
-  struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
-  struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
-  struct ParallelLookup *parallel_lookup;
-  size_t size;
-  char *buf;
-  char *scope;
-
-  handle->lookup_request = NULL;
-  if (1 != rd_count)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Number of keys %d != 1.",
-                rd_count);
-    cleanup_consume_ticket_handle (handle);
-    GNUNET_CONTAINER_DLL_remove (handle->client->consume_op_head,
-                                 handle->client->consume_op_tail,
-                                 handle);
-    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
-    return;
-  }
-
-  //Decrypt
-  ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
-
-  buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
-
-  //Calculate symmetric key from ecdh parameters
-  GNUNET_assert (GNUNET_OK == 
-                 GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
-                                           ecdh_key,
-                                           &new_key_hash));
-  create_sym_key_from_ecdh (&new_key_hash,
-                            &enc_key,
-                            &enc_iv);
-  size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
-                                          rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
-                                          &enc_key,
-                                          &enc_iv,
-                                          buf);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Decrypted bytes: %zd Expected bytes: %zd\n",
-              size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
-  GNUNET_STATISTICS_update (stats,
-                            "abe_key_lookup_time_total",
-                            GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us,
-                            GNUNET_YES);
-  GNUNET_STATISTICS_update (stats,
-                            "abe_key_lookups_count",
-                            1,
-                            GNUNET_YES);
-  scopes = GNUNET_strdup (buf);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Scopes %s\n", scopes);
-  handle->key = GNUNET_ABE_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
-                                                  rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
-                                                  - strlen (scopes) - 1);
-
-  for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Looking up %s\n", scope);
-    parallel_lookup = GNUNET_new (struct ParallelLookup);
-    parallel_lookup->handle = handle;
-    parallel_lookup->label = GNUNET_strdup (scope);
-    parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get();
-    parallel_lookup->lookup_request
-      = GNUNET_GNS_lookup (gns_handle,
-                           scope,
-                           &handle->ticket.identity,
-                           GNUNET_GNSRECORD_TYPE_ID_ATTR,
-                           GNUNET_GNS_LO_DEFAULT,
-                           &process_parallel_lookup2,
-                           parallel_lookup);
-    GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
-                                 handle->parallel_lookups_tail,
-                                 parallel_lookup);
-  }
-  GNUNET_free (scopes);
-  GNUNET_free (buf);
-  handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
-                                                    &abort_parallel_lookups2,
-                                                    handle);
-}
-
-
-static void
-handle_consume_ticket_message (void *cls,
-                               const struct ConsumeTicketMessage *cm)
-{
-  struct ConsumeTicketHandle *ch;
-  struct IdpClient *idp = cls;
-  char* rnd_label;
-
-  ch = GNUNET_new (struct ConsumeTicketHandle);
-  ch->r_id = ntohl (cm->id);
-  ch->client = idp;
-  ch->identity = cm->identity;
-  ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
-  GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
-                                      &ch->identity_pub);
-  ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
-  rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
-                                                   sizeof (uint64_t));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Looking for ABE key under %s\n", rnd_label);
-  ch->lookup_start_time = GNUNET_TIME_absolute_get ();
-  ch->lookup_request
-    = GNUNET_GNS_lookup (gns_handle,
-                         rnd_label,
-                         &ch->ticket.identity,
-                         GNUNET_GNSRECORD_TYPE_ABE_KEY,
-                         GNUNET_GNS_LO_DEFAULT,
-                         &process_consume_abe_key,
-                         ch);
-  GNUNET_CONTAINER_DLL_insert (idp->consume_op_head,
-                               idp->consume_op_tail,
-                               ch);
-  GNUNET_free (rnd_label);
-  GNUNET_SERVICE_client_continue (idp->client);
-}
-
-/**
- * Cleanup attribute store handle
- *
- * @param handle handle to clean up
- */
-static void
-cleanup_as_handle (struct AttributeStoreHandle *handle)
-{
-  if (NULL != handle->ns_qe)
-    GNUNET_NAMESTORE_cancel (handle->ns_qe);
-  if (NULL != handle->claim)
-    GNUNET_free (handle->claim);
-  if (NULL != handle->abe_key)
-    GNUNET_ABE_cpabe_delete_master_key (handle->abe_key);
-  GNUNET_free (handle);
-}
-
-static void
-attr_store_cont (void *cls,
-                 int32_t success,
-                 const char *emsg)
-{
-  struct AttributeStoreHandle *as_handle = cls;
-  struct GNUNET_MQ_Envelope *env;
-  struct AttributeStoreResultMessage *acr_msg;
-
-  as_handle->ns_qe = NULL;
-  GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head,
-                               as_handle->client->store_op_tail,
-                               as_handle);
-
-  if (GNUNET_SYSERR == success)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to store attribute %s\n",
-                emsg);
-    cleanup_as_handle (as_handle);
-    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending ATTRIBUTE_STORE_RESPONSE message\n");
-  env = GNUNET_MQ_msg (acr_msg,
-                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
-  acr_msg->id = htonl (as_handle->r_id);
-  acr_msg->op_result = htonl (GNUNET_OK);
-  GNUNET_MQ_send (as_handle->client->mq,
-                  env);
-  cleanup_as_handle (as_handle);
-}
-
-static void
-attr_store_task (void *cls)
-{
-  struct AttributeStoreHandle *as_handle = cls;
-  struct GNUNET_GNSRECORD_Data rd[1];
-  char* buf;
-  char* policy;
-  char* enc_buf;
-  char* rd_buf;
-  size_t enc_size;
-  size_t buf_size;
-  uint32_t attr_ver;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Storing attribute\n");
-  buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (as_handle->claim);
-  buf = GNUNET_malloc (buf_size);
-
-  GNUNET_IDENTITY_ATTRIBUTE_serialize (as_handle->claim,
-                                       buf);
-
-  GNUNET_asprintf (&policy,
-                   "%s_%lu",
-                   as_handle->claim->name,
-                   as_handle->claim->version);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Encrypting with policy %s\n", policy);
-  /**
-   * Encrypt the attribute value and store in namestore
-   */
-  enc_size = GNUNET_ABE_cpabe_encrypt (buf,
-                                       buf_size,
-                                       policy, //Policy
-                                       as_handle->abe_key,
-                                       (void**)&enc_buf);
-  if (GNUNET_SYSERR == enc_size)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to encrypt with policy %s\n",
-                policy);
-    GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head,
-                                 as_handle->client->store_op_tail,
-                                 as_handle);
-
-    cleanup_as_handle (as_handle);
-    GNUNET_free (buf);
-    GNUNET_free (policy);
-    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
-    return;
-  }
-  GNUNET_free (buf);
-  GNUNET_free (policy);
-  rd[0].data_size = enc_size + sizeof (uint32_t);
-  rd_buf = GNUNET_malloc (rd[0].data_size);
-  attr_ver = htonl (as_handle->claim->version);
-  GNUNET_memcpy (rd_buf,
-                 &attr_ver,
-                 sizeof (uint32_t));
-  GNUNET_memcpy (rd_buf+sizeof (uint32_t),
-                 enc_buf,
-                 enc_size);
-  rd[0].data = rd_buf;
-  rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
-  rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
-  rd[0].expiration_time = as_handle->exp.rel_value_us;
-  as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
-                                                     &as_handle->identity,
-                                                     as_handle->claim->name,
-                                                     1,
-                                                     rd,
-                                                     &attr_store_cont,
-                                                     as_handle);
-  GNUNET_free (enc_buf);
-  GNUNET_free (rd_buf);
-}
-
-
-static void
-store_after_abe_bootstrap (void *cls,
-                           struct GNUNET_ABE_AbeMasterKey *abe_key)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Finished ABE bootstrap\n");
-  struct AttributeStoreHandle *ash = cls;
-  ash->abe_key = abe_key;
-  GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
-}
-
-static int
-check_attribute_store_message(void *cls,
-                              const struct AttributeStoreMessage *sam)
-{
-  uint16_t size;
-
-  size = ntohs (sam->header.size);
-  if (size <= sizeof (struct AttributeStoreMessage))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-
-static void
-handle_attribute_store_message (void *cls,
-                                const struct AttributeStoreMessage *sam)
-{
-  struct AttributeStoreHandle *as_handle;
-  struct IdpClient *idp = cls;
-  size_t data_len;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received ATTRIBUTE_STORE message\n");
-
-  data_len = ntohs (sam->attr_len);
-
-  as_handle = GNUNET_new (struct AttributeStoreHandle);
-  as_handle->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&sam[1],
-                                                            data_len);
-
-  as_handle->r_id = ntohl (sam->id);
-  as_handle->identity = sam->identity;
-  as_handle->exp.rel_value_us = GNUNET_ntohll (sam->exp);
-  GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
-                                      &as_handle->identity_pkey);
-
-  GNUNET_SERVICE_client_continue (idp->client);
-  as_handle->client = idp;
-  GNUNET_CONTAINER_DLL_insert (idp->store_op_head,
-                               idp->store_op_tail,
-                               as_handle);
-  bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
-}
-
-static void
-cleanup_attribute_iter_handle (struct AttributeIterator *ai)
-{
-  if (NULL != ai->abe_key)
-    GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
-  GNUNET_free (ai);
-}
-
-static void
-attr_iter_error (void *cls)
-{
-  struct AttributeIterator *ai = cls;
-  //TODO
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Failed to iterate over attributes\n");
-  GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
-                               ai->client->attr_iter_tail,
-                               ai);
-  cleanup_attribute_iter_handle (ai);
-  GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
-}
-
-static void
-attr_iter_finished (void *cls)
-{
-  struct AttributeIterator *ai = cls;
-  struct GNUNET_MQ_Envelope *env;
-  struct AttributeResultMessage *arm;
-
-  env = GNUNET_MQ_msg (arm,
-                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
-  arm->id = htonl (ai->request_id);
-  arm->attr_len = htons (0);
-  GNUNET_MQ_send (ai->client->mq, env);
-  GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
-                               ai->client->attr_iter_tail,
-                               ai);
-  cleanup_attribute_iter_handle (ai);
-}
-
-static void
-attr_iter_cb (void *cls,
-              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-              const char *label,
-              unsigned int rd_count,
-              const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct AttributeIterator *ai = cls;
-  struct AttributeResultMessage *arm;
-  struct GNUNET_ABE_AbeKey *key;
-  struct GNUNET_MQ_Envelope *env;
-  ssize_t msg_extra_len;
-  char* attr_ser;
-  char* attrs[2];
-  char* data_tmp;
-  char* policy;
-  uint32_t attr_ver;
-
-  if (rd_count != 1)
-  {
-    GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
-                                         1);
-    return;
-  }
-
-  if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type)
-  {
-    GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
-                                         1);
-    return;
-  }
-  attr_ver = ntohl(*((uint32_t*)rd->data));
-  GNUNET_asprintf (&policy, "%s_%lu",
-                   label, attr_ver);
-  attrs[0] = policy;
-  attrs[1] = 0;
-  key = GNUNET_ABE_cpabe_create_key (ai->abe_key,
-                                     attrs);
-  msg_extra_len = GNUNET_ABE_cpabe_decrypt (rd->data+sizeof (uint32_t),
-                                            rd->data_size-sizeof (uint32_t),
-                                            key,
-                                            (void**)&attr_ser);
-  if (GNUNET_SYSERR == msg_extra_len)
-  {
-    GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
-                                         1);
-    return;
-  }
-
-  GNUNET_ABE_cpabe_delete_key (key,
-                               GNUNET_YES);
-  //GNUNET_free (policy);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Found attribute: %s\n", label);
-  env = GNUNET_MQ_msg_extra (arm,
-                             msg_extra_len,
-                             GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
-  arm->id = htonl (ai->request_id);
-  arm->attr_len = htons (msg_extra_len);
-  GNUNET_CRYPTO_ecdsa_key_get_public (zone,
-                                      &arm->identity);
-  data_tmp = (char *) &arm[1];
-  GNUNET_memcpy (data_tmp,
-                 attr_ser,
-                 msg_extra_len);
-  GNUNET_MQ_send (ai->client->mq, env);
-  GNUNET_free (attr_ser);
-  GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
-  ai->abe_key = NULL;
-}
-
-
-void
-iterate_after_abe_bootstrap (void *cls,
-                             struct GNUNET_ABE_AbeMasterKey *abe_key)
-{
-  struct AttributeIterator *ai = cls;
-  ai->abe_key = abe_key;
-  ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
-                                                     &ai->identity,
-                                                     &attr_iter_error,
-                                                     ai,
-                                                     &attr_iter_cb,
-                                                     ai,
-                                                     &attr_iter_finished,
-                                                     ai);
-}
-
-
-static void
-iterate_next_after_abe_bootstrap (void *cls,
-                                  struct GNUNET_ABE_AbeMasterKey *abe_key)
-{
-  struct AttributeIterator *ai = cls;
-  ai->abe_key = abe_key;
-  GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
-                                       1);
-}
-
-
-
-static void
-handle_iteration_start (void *cls,
-                        const struct AttributeIterationStartMessage *ais_msg)
-{
-  struct IdpClient *idp = cls;
-  struct AttributeIterator *ai;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received ATTRIBUTE_ITERATION_START message\n");
-  ai = GNUNET_new (struct AttributeIterator);
-  ai->request_id = ntohl (ais_msg->id);
-  ai->client = idp;
-  ai->identity = ais_msg->identity;
-
-  GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head,
-                               idp->attr_iter_tail,
-                               ai);
-  bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
-  GNUNET_SERVICE_client_continue (idp->client);
-}
-
-
-static void
-handle_iteration_stop (void *cls,
-                       const struct AttributeIterationStopMessage *ais_msg)
-{
-  struct IdpClient *idp = cls;
-  struct AttributeIterator *ai;
-  uint32_t rid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received `%s' message\n",
-              "ATTRIBUTE_ITERATION_STOP");
-  rid = ntohl (ais_msg->id);
-  for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
-    if (ai->request_id == rid)
-      break;
-  if (NULL == ai)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVICE_client_drop (idp->client);
-    return;
-  }
-  GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head,
-                               idp->attr_iter_tail,
-                               ai);
-  GNUNET_free (ai);
-  GNUNET_SERVICE_client_continue (idp->client);
-}
-
-
-static void
-handle_iteration_next (void *cls,
-                       const struct AttributeIterationNextMessage *ais_msg)
-{
-  struct IdpClient *idp = cls;
-  struct AttributeIterator *ai;
-  uint32_t rid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received ATTRIBUTE_ITERATION_NEXT message\n");
-  rid = ntohl (ais_msg->id);
-  for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
-    if (ai->request_id == rid)
-      break;
-  if (NULL == ai)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVICE_client_drop (idp->client);
-    return;
-  }
-  bootstrap_abe (&ai->identity,
-                 &iterate_next_after_abe_bootstrap,
-                 ai,
-                 GNUNET_NO);
-  GNUNET_SERVICE_client_continue (idp->client);
-}
-
-/**
- * Ticket iteration processor result
- */
-enum ZoneIterationResult
-{
-  /**
-   * Iteration start.
-   */
-  IT_START = 0,
-
-  /**
-   * Found tickets,
-   * Continue to iterate with next iteration_next call
-   */
-  IT_SUCCESS_MORE_AVAILABLE = 1,
-
-  /**
-   * Iteration complete
-   */
-  IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
-};
-
-
-/**
- * Context for ticket iteration
- */
-struct TicketIterationProcResult
-{
-  /**
-   * The ticket iteration handle
-   */
-  struct TicketIteration *ti;
-
-  /**
-   * Iteration result: iteration done?
-   * #IT_SUCCESS_MORE_AVAILABLE:  if there may be more results overall but
-   * we got one for now and have sent it to the client
-   * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
-   * #IT_START: if we are still trying to find a result.
-   */
-  int res_iteration_finished;
-
-};
-
-static void
-cleanup_ticket_iter_handle (struct TicketIteration *ti)
-{
-  GNUNET_free (ti);
-}
-
-/**
- * Process ticket from database
- *
- * @param cls struct TicketIterationProcResult
- * @param ticket the ticket
- * @param attrs the attributes
- */
-static void
-ticket_iterate_proc (void *cls,
-                     const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                     const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
-{
-  struct TicketIterationProcResult *proc = cls;
-
-  if (NULL == ticket)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Iteration done\n");
-    proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
-    return;
-  }
-  proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
-  send_ticket_result (proc->ti->client,
-                      proc->ti->r_id,
-                      ticket,
-                      attrs);
-
-}
-
-/**
- * Perform ticket iteration step
- *
- * @param ti ticket iterator to process
- */
-static void
-run_ticket_iteration_round (struct TicketIteration *ti)
-{
-  struct TicketIterationProcResult proc;
-  struct GNUNET_MQ_Envelope *env;
-  struct TicketResultMessage *trm;
-  int ret;
-
-  memset (&proc, 0, sizeof (proc));
-  proc.ti = ti;
-  proc.res_iteration_finished = IT_START;
-  while (IT_START == proc.res_iteration_finished)
-  {
-    if (GNUNET_SYSERR ==
-        (ret = TKT_database->iterate_tickets (TKT_database->cls,
-                                              &ti->identity,
-                                              ti->is_audience,
-                                              ti->offset,
-                                              &ticket_iterate_proc,
-                                              &proc)))
-    {
-      GNUNET_break (0);
-      break;
-    }
-    if (GNUNET_NO == ret)
-      proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
-    ti->offset++;
-  }
-  if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "More results available\n");
-    return; /* more later */
-  }
-  /* send empty response to indicate end of list */
-  env = GNUNET_MQ_msg (trm,
-                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
-  trm->id = htonl (ti->r_id);
-  GNUNET_MQ_send (ti->client->mq,
-                  env);
-  GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
-                               ti->client->ticket_iter_tail,
-                               ti);
-  cleanup_ticket_iter_handle (ti);
-}
-
-static void
-handle_ticket_iteration_start (void *cls,
-                               const struct TicketIterationStartMessage *tis_msg)
-{
-  struct IdpClient *client = cls;
-  struct TicketIteration *ti;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received TICKET_ITERATION_START message\n");
-  ti = GNUNET_new (struct TicketIteration);
-  ti->r_id = ntohl (tis_msg->id);
-  ti->offset = 0;
-  ti->client = client;
-  ti->identity = tis_msg->identity;
-  ti->is_audience = ntohl (tis_msg->is_audience);
-
-  GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
-                               client->ticket_iter_tail,
-                               ti);
-  run_ticket_iteration_round (ti);
-  GNUNET_SERVICE_client_continue (client->client);
-}
-
-
-static void
-handle_ticket_iteration_stop (void *cls,
-                              const struct TicketIterationStopMessage *tis_msg)
-{
-  struct IdpClient *client = cls;
-  struct TicketIteration *ti;
-  uint32_t rid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received `%s' message\n",
-              "TICKET_ITERATION_STOP");
-  rid = ntohl (tis_msg->id);
-  for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
-    if (ti->r_id == rid)
-      break;
-  if (NULL == ti)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVICE_client_drop (client->client);
-    return;
-  }
-  GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
-                               client->ticket_iter_tail,
-                               ti);
-  cleanup_ticket_iter_handle (ti);
-  GNUNET_SERVICE_client_continue (client->client);
-}
-
-
-static void
-handle_ticket_iteration_next (void *cls,
-                              const struct TicketIterationNextMessage *tis_msg)
-{
-  struct IdpClient *client = cls;
-  struct TicketIteration *ti;
-  uint32_t rid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received TICKET_ITERATION_NEXT message\n");
-  rid = ntohl (tis_msg->id);
-  for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
-    if (ti->r_id == rid)
-      break;
-  if (NULL == ti)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVICE_client_drop (client->client);
-    return;
-  }
-  run_ticket_iteration_round (ti);
-  GNUNET_SERVICE_client_continue (client->client);
-}
-
-
-
-
-/**
- * Main function that will be run
- *
- * @param cls closure
- * @param c the configuration used 
- * @param server the service handle
- */
-static void
-run (void *cls,
-     const struct GNUNET_CONFIGURATION_Handle *c,
-     struct GNUNET_SERVICE_Handle *server)
-{
-  char *database;
-  cfg = c;
-
-  stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
-
-  //Connect to identity and namestore services
-  ns_handle = GNUNET_NAMESTORE_connect (cfg);
-  if (NULL == ns_handle)
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
-  }
-
-  gns_handle = GNUNET_GNS_connect (cfg);
-  if (NULL == gns_handle)
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
-  }
-  credential_handle = GNUNET_CREDENTIAL_connect (cfg);
-  if (NULL == credential_handle)
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
-  }
-  identity_handle = GNUNET_IDENTITY_connect (cfg,
-                                             NULL,
-                                             NULL);
-  /* Loading DB plugin */
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg,
-                                             "identity-provider",
-                                             "database",
-                                             &database))
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "No database backend configured\n");
-  GNUNET_asprintf (&db_lib_name,
-                   "libgnunet_plugin_identity_provider_%s",
-                   database);
-  TKT_database = GNUNET_PLUGIN_load (db_lib_name,
-                                     (void *) cfg);
-  GNUNET_free (database);
-  if (NULL == TKT_database)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Could not load database backend `%s'\n",
-                db_lib_name);
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_time (cfg,
-                                           "identity-provider",
-                                           "TOKEN_EXPIRATION_INTERVAL",
-                                           &token_expiration_interval))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Time window for zone iteration: %s\n",
-                GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
-                                                        GNUNET_YES));
-  } else {
-    token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
-  }
-
-  GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
-}
-
-/**
- * Called whenever a client is disconnected.
- *
- * @param cls closure
- * @param client identification of the client
- * @param app_ctx @a client
- */
-static void
-client_disconnect_cb (void *cls,
-                      struct GNUNET_SERVICE_Client *client,
-                      void *app_ctx)
-{
-  struct IdpClient *idp = app_ctx;
-  struct AttributeIterator *ai;
-  struct TicketIteration *ti;
-  struct TicketRevocationHandle *rh;
-  struct TicketIssueHandle *iss;
-  struct ConsumeTicketHandle *ct;
-  struct AttributeStoreHandle *as;
-
-  //TODO other operations
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Client %p disconnected\n",
-              client);
-
-  while (NULL != (iss = idp->issue_op_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (idp->issue_op_head,
-                                 idp->issue_op_tail,
-                                 iss);
-    cleanup_ticket_issue_handle (iss);
-  }
-  while (NULL != (ct = idp->consume_op_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
-                                 idp->consume_op_tail,
-                                 ct);
-    cleanup_consume_ticket_handle (ct);
-  }
-  while (NULL != (as = idp->store_op_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (idp->store_op_head,
-                                 idp->store_op_tail,
-                                 as);
-    cleanup_as_handle (as);
-  }
-
-  while (NULL != (ai = idp->attr_iter_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head,
-                                 idp->attr_iter_tail,
-                                 ai);
-    cleanup_attribute_iter_handle (ai);
-  }
-  while (NULL != (rh = idp->revoke_op_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head,
-                                 idp->revoke_op_tail,
-                                 rh);
-    cleanup_revoke_ticket_handle (rh);
-  }
-  while (NULL != (ti = idp->ticket_iter_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
-                                 idp->ticket_iter_tail,
-                                 ti);
-    cleanup_ticket_iter_handle (ti);
-  }
-  GNUNET_free (idp);
-}
-
-
-/**
- * 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 internal namestore client structure for this client
- */
-static void *
-client_connect_cb (void *cls,
-                   struct GNUNET_SERVICE_Client *client,
-                   struct GNUNET_MQ_Handle *mq)
-{
-  struct IdpClient *idp;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Client %p connected\n",
-              client);
-  idp = GNUNET_new (struct IdpClient);
-  idp->client = client;
-  idp->mq = mq;
-  return idp;
-}
-
-
-
-/**
- * Define "main" method using service macro.
- */
-GNUNET_SERVICE_MAIN
-("identity-provider",
- GNUNET_SERVICE_OPTION_NONE,
- &run,
- &client_connect_cb,
- &client_disconnect_cb,
- NULL,
- GNUNET_MQ_hd_var_size (attribute_store_message,
-                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
-                        struct AttributeStoreMessage,
-                        NULL),
- GNUNET_MQ_hd_fixed_size (iteration_start, 
-                          GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
-                          struct AttributeIterationStartMessage,
-                          NULL),
- GNUNET_MQ_hd_fixed_size (iteration_next, 
-                          GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
-                          struct AttributeIterationNextMessage,
-                          NULL),
- GNUNET_MQ_hd_fixed_size (iteration_stop, 
-                          GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
-                          struct AttributeIterationStopMessage,
-                          NULL),
- GNUNET_MQ_hd_var_size (issue_ticket_message,
-                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET,
-                        struct IssueTicketMessage,
-                        NULL),
- GNUNET_MQ_hd_var_size (consume_ticket_message,
-                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
-                        struct ConsumeTicketMessage,
-                        NULL),
- GNUNET_MQ_hd_fixed_size (ticket_iteration_start, 
-                          GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
-                          struct TicketIterationStartMessage,
-                          NULL),
- GNUNET_MQ_hd_fixed_size (ticket_iteration_next, 
-                          GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
-                          struct TicketIterationNextMessage,
-                          NULL),
- GNUNET_MQ_hd_fixed_size (ticket_iteration_stop, 
-                          GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
-                          struct TicketIterationStopMessage,
-                          NULL),
- GNUNET_MQ_hd_var_size (revoke_ticket_message,
-                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET,
-                        struct RevokeTicketMessage,
-                        NULL),
- GNUNET_MQ_handler_end());
-/* end of gnunet-service-identity-provider.c */
diff --git a/src/identity-provider/identity-provider.conf b/src/identity-provider/identity-provider.conf
deleted file mode 100644 (file)
index 99c0a50..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-[identity-provider]
-START_ON_DEMAND = NO
-RUN_PER_USER = YES
-#PORT = 2108
-HOSTNAME = localhost
-BINARY = gnunet-service-identity-provider
-ACCEPT_FROM = 127.0.0.1;
-ACCEPT_FROM6 = ::1;
-UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-identity-provider.sock
-UNIX_MATCH_UID = NO
-UNIX_MATCH_GID = YES
-TOKEN_EXPIRATION_INTERVAL = 30 m
-DATABASE = sqlite
-
-[identity-rest-plugin]
-#ADDRESS = https://identity.gnu:8000#/login
-ADDRESS = https://reclaim.ui/#/login
-PSW = secret
-JWT_SECRET = secret
-EXPIRATION_TIME = 3600
-
-[identity-provider-sqlite]
-FILENAME = $GNUNET_DATA_HOME/identity-provider/sqlite.db
diff --git a/src/identity-provider/identity-token.conf b/src/identity-provider/identity-token.conf
deleted file mode 100644 (file)
index f29f6cd..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-[identity-token]
-BINARY=gnunet-service-identity-token
diff --git a/src/identity-provider/identity_provider.h b/src/identity-provider/identity_provider.h
deleted file mode 100644 (file)
index 6a4b776..0000000
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2016 GNUnet e.V.
-
-     GNUnet is free software: you can redistribute it and/or modify it
-     under the terms of the GNU Affero General Public License as published
-     by the Free Software Foundation, either version 3 of the License,
-     or (at your option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     Affero General Public License for more details.
-    
-     You should have received a copy of the GNU Affero General Public License
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @author Martin Schanzenbach
- * @file identity-provider/identity_provider.h
- *
- * @brief Common type definitions for the identity provider
- *        service and API.
- */
-#ifndef IDENTITY_PROVIDER_H
-#define IDENTITY_PROVIDER_H
-
-#include "gnunet_common.h"
-
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-/**
- * Use to store an identity attribute
- */
-struct AttributeStoreMessage
-{
-  /**
-   * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-  /**
-   * The length of the attribute
-   */
-  uint32_t attr_len GNUNET_PACKED;
-
-  /**
-   * The expiration interval of the attribute
-   */
-  uint64_t exp GNUNET_PACKED;
-
-  /**
-   * Identity
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
-
-  /* followed by the serialized attribute */
-
-};
-
-/**
- * Attribute store response message
- */
-struct AttributeStoreResultMessage
-{
-  /**
-   * Message header
-   */
-  struct GNUNET_MessageHeader header;
-  
-  /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-  /**
-   * #GNUNET_SYSERR on failure, #GNUNET_OK on success
-   */
-  int32_t op_result GNUNET_PACKED;
-
-};
-
-/**
- * Attribute is returned from the idp.
- */
-struct AttributeResultMessage
-{
-  /**
-   * Message header
-   */
-  struct GNUNET_MessageHeader header;
-
-   /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-  /**
-   * Length of serialized attribute data
-   */
-  uint16_t attr_len GNUNET_PACKED;
-
-  /**
-   * always zero (for alignment)
-   */
-  uint16_t reserved GNUNET_PACKED;
-
-  /**
-   * The public key of the identity.
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
-
-  /* followed by:
-   * serialized attribute data
-   */
-};
-
-
-/**
- * Start a attribute iteration for the given identity
- */
-struct AttributeIterationStartMessage
-{
-  /**
-   * Message
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-  /**
-   * Identity.
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
-
-};
-
-
-/**
- * Ask for next result of attribute iteration for the given operation
- */
-struct AttributeIterationNextMessage
-{
-  /**
-   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-};
-
-
-/**
- * Stop attribute iteration for the given operation
- */
-struct AttributeIterationStopMessage
-{
-  /**
-   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-};
-
-/**
- * Start a ticket iteration for the given identity
- */
-struct TicketIterationStartMessage
-{
-  /**
-   * Message
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-  /**
-   * Identity.
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
-
-  /**
-   * Identity is audience or issuer
-   */
-  uint32_t is_audience GNUNET_PACKED;
-};
-
-
-/**
- * Ask for next result of ticket iteration for the given operation
- */
-struct TicketIterationNextMessage
-{
-  /**
-   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-};
-
-
-/**
- * Stop ticket iteration for the given operation
- */
-struct TicketIterationStopMessage
-{
-  /**
-   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-};
-
-
-
-/**
- * Ticket issue message
- */
-struct IssueTicketMessage
-{
-  /**
-   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-  /**
-   * Identity.
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
-
-  /**
-   * Requesting party.
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey rp;
-
-  /**
-   * length of serialized attribute list
-   */
-  uint32_t attr_len GNUNET_PACKED;
-
-  //Followed by a serialized attribute list
-};
-
-/**
- * Ticket revoke message
- */
-struct RevokeTicketMessage
-{
-  /**
-   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-  /**
-   * Identity.
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
-
-  /**
-   * length of serialized attribute list
-   */
-  uint32_t attrs_len GNUNET_PACKED;
-
-  //Followed by a ticket and serialized attribute list
-};
-
-/**
- * Ticket revoke message
- */
-struct RevokeTicketResultMessage
-{
-  /**
-   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-  /**
-   * Revocation result
-   */
-  uint32_t success GNUNET_PACKED;
-};
-
-
-/**
- * Ticket result message
- */
-struct TicketResultMessage
-{
-  /**
-   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-};
-
-/**
- * Ticket consume message
- */
-struct ConsumeTicketMessage
-{
-  /**
-   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-  /**
-   * Identity.
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
-
-  //Followed by a serialized ticket
-};
-
-/**
- * Attribute list is returned from the idp.
- */
-struct ConsumeTicketResultMessage
-{
-  /**
-   * Message header
-   */
-  struct GNUNET_MessageHeader header;
-
-   /**
-   * Unique identifier for this request (for key collisions).
-   */
-  uint32_t id GNUNET_PACKED;
-
-  /**
-   * Length of serialized attribute data
-   */
-  uint16_t attrs_len GNUNET_PACKED;
-
-  /**
-   * always zero (for alignment)
-   */
-  uint16_t reserved GNUNET_PACKED;
-
-  /**
-   * The public key of the identity.
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
-
-  /* followed by:
-   * serialized attributes data
-   */
-};
-
-
-
-GNUNET_NETWORK_STRUCT_END
-
-#endif
diff --git a/src/identity-provider/identity_provider_api.c b/src/identity-provider/identity_provider_api.c
deleted file mode 100644 (file)
index 33efe72..0000000
+++ /dev/null
@@ -1,1383 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2016 GNUnet e.V.
-
-     GNUnet is free software: you can redistribute it and/or modify it
-     under the terms of the GNU Affero General Public License as published
-     by the Free Software Foundation, either version 3 of the License,
-     or (at your option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     Affero General Public License for more details.
-    
-     You should have received a copy of the GNU Affero General Public License
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file identity-provider/identity_provider_api.c
- * @brief api to interact with the identity provider service
- * @author Martin Schanzenbach
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_constants.h"
-#include "gnunet_protocols.h"
-#include "gnunet_mq_lib.h"
-#include "gnunet_identity_provider_service.h"
-#include "gnunet_identity_attribute_lib.h"
-#include "identity_provider.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__)
-
-
-/**
- * Handle for an operation with the service.
- */
-struct GNUNET_IDENTITY_PROVIDER_Operation
-{
-
-  /**
-   * Main handle.
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Handle *h;
-
-  /**
-   * We keep operations in a DLL.
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Operation *next;
-
-  /**
-   * We keep operations in a DLL.
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Operation *prev;
-
-  /**
-   * Message to send to the service.
-   * Allocated at the end of this struct.
-   */
-  const struct GNUNET_MessageHeader *msg;
-
-  /**
-   * Continuation to invoke after attribute store call
-   */
-  GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus as_cb;
-
-  /**
-   * Attribute result callback
-   */
-  GNUNET_IDENTITY_PROVIDER_AttributeResult ar_cb;
-
-  /**
-   * Revocation result callback
-   */
-  GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus rvk_cb;
-
-  /**
-   * Ticket result callback
-   */
-  GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb;
-
-  /**
-   * Envelope with the message for this queue entry.
-   */
-  struct GNUNET_MQ_Envelope *env;
-
-  /**
-   * request id
-   */
-  uint32_t r_id;
-
-  /**
-   * Closure for @e cont or @e cb.
-   */
-  void *cls;
-
-};
-
-/**
- * Handle for a ticket iterator operation
- */
-struct GNUNET_IDENTITY_PROVIDER_TicketIterator
-{
-
-  /**
-   * Kept in a DLL.
-   */
-  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *next;
-
-  /**
-   * Kept in a DLL.
-   */
-  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *prev;
-
-  /**
-   * Main handle to access the idp.
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Handle *h;
-
-  /**
-   * Function to call on completion.
-   */
-  GNUNET_SCHEDULER_TaskCallback finish_cb;
-
-  /**
-   * Closure for @e error_cb.
-   */
-  void *finish_cb_cls;
-
-  /**
-   * The continuation to call with the results
-   */
-  GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb;
-
-  /**
-   * Closure for @e tr_cb.
-   */
-  void *cls;
-
-  /**
-   * Function to call on errors.
-   */
-  GNUNET_SCHEDULER_TaskCallback error_cb;
-
-  /**
-   * Closure for @e error_cb.
-   */
-  void *error_cb_cls;
-
-  /**
-   * Envelope of the message to send to the service, if not yet
-   * sent.
-   */
-  struct GNUNET_MQ_Envelope *env;
-
-  /**
-   * The operation id this zone iteration operation has
-   */
-  uint32_t r_id;
-
-};
-
-
-/**
- * Handle for a attribute iterator operation
- */
-struct GNUNET_IDENTITY_PROVIDER_AttributeIterator
-{
-
-  /**
-   * Kept in a DLL.
-   */
-  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *next;
-
-  /**
-   * Kept in a DLL.
-   */
-  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *prev;
-
-  /**
-   * Main handle to access the idp.
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Handle *h;
-
-  /**
-   * Function to call on completion.
-   */
-  GNUNET_SCHEDULER_TaskCallback finish_cb;
-
-  /**
-   * Closure for @e error_cb.
-   */
-  void *finish_cb_cls;
-
-  /**
-   * The continuation to call with the results
-   */
-  GNUNET_IDENTITY_PROVIDER_AttributeResult proc;
-
-  /**
-   * Closure for @e proc.
-   */
-  void *proc_cls;
-
-  /**
-   * Function to call on errors.
-   */
-  GNUNET_SCHEDULER_TaskCallback error_cb;
-
-  /**
-   * Closure for @e error_cb.
-   */
-  void *error_cb_cls;
-
-  /**
-   * Envelope of the message to send to the service, if not yet
-   * sent.
-   */
-  struct GNUNET_MQ_Envelope *env;
-
-  /**
-   * Private key of the zone.
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
-
-  /**
-   * The operation id this zone iteration operation has
-   */
-  uint32_t r_id;
-
-};
-
-
-/**
- * Handle for the service.
- */
-struct GNUNET_IDENTITY_PROVIDER_Handle
-{
-  /**
-   * Configuration to use.
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Socket (if available).
-   */
-  struct GNUNET_CLIENT_Connection *client;
-
-  /**
-   * Closure for 'cb'.
-   */
-  void *cb_cls;
-
-  /**
-   * Head of active operations.
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Operation *op_head;
-
-  /**
-   * Tail of active operations.
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail;
-
-  /**
-   * Head of active iterations
-   */
-  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_head;
-
-  /**
-   * Tail of active iterations
-   */
-  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_tail;
-
-  /**
-   * Head of active iterations
-   */
-  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_head;
-
-  /**
-   * Tail of active iterations
-   */
-  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_tail;
-
-
-  /**
-   * Currently pending transmission request, or NULL for none.
-   */
-  struct GNUNET_CLIENT_TransmitHandle *th;
-
-  /**
-   * Task doing exponential back-off trying to reconnect.
-   */
-  struct GNUNET_SCHEDULER_Task * reconnect_task;
-
-  /**
-   * Time for next connect retry.
-   */
-  struct GNUNET_TIME_Relative reconnect_backoff;
-
-  /**
-   * Connection to service (if available).
-   */
-  struct GNUNET_MQ_Handle *mq;
-
-  /**
-   * Request Id generator.  Incremented by one for each request.
-   */
-  uint32_t r_id_gen;
-
-  /**
-   * Are we polling for incoming messages right now?
-   */
-  int in_receive;
-
-};
-
-/**
- * Try again to connect to the service.
- *
- * @param h handle to the identity provider service.
- */
-static void
-reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h);
-
-/**
- * Reconnect
- *
- * @param cls the handle
- */
-static void
-reconnect_task (void *cls)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls;
-
-  handle->reconnect_task = NULL;
-  reconnect (handle);
-}
-
-
-/**
- * Disconnect from service and then reconnect.
- *
- * @param handle our service
- */
-static void
-force_reconnect (struct GNUNET_IDENTITY_PROVIDER_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);
-}
-
-/**
- * Free @a it.
- *
- * @param it entry to free
- */
-static void
-free_it (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
-
-  GNUNET_CONTAINER_DLL_remove (h->it_head,
-                               h->it_tail,
-                               it);
-  if (NULL != it->env)
-    GNUNET_MQ_discard (it->env);
-  GNUNET_free (it);
-}
-
-static void
-free_op (struct GNUNET_IDENTITY_PROVIDER_Operation* op)
-{
-  if (NULL == op)
-    return;
-  if (NULL != op->env)
-    GNUNET_MQ_discard (op->env);
-  GNUNET_free(op);
-}
-
-
-/**
- * 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_GNS_Handle *`
- * @param error error code
- */
-static void
-mq_error_handler (void *cls,
-                  enum GNUNET_MQ_Error error)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls;
-  force_reconnect (handle);
-}
-
-/**
- * Handle an incoming message of type
- * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
- *
- * @param cls
- * @param msg the message we received
- */
-static void
-handle_attribute_store_response (void *cls,
-                             const struct AttributeStoreResultMessage *msg)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
-  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
-  uint32_t r_id = ntohl (msg->id);
-  int res;
-  const char *emsg;
-
-  for (op = h->op_head; NULL != op; op = op->next)
-    if (op->r_id == r_id)
-      break;
-  if (NULL == op)
-    return;
-
-  res = ntohl (msg->op_result);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Received ATTRIBUTE_STORE_RESPONSE with result %d\n",
-       res);
-
-  /* TODO: add actual error message to response... */
-  if (GNUNET_SYSERR == res)
-    emsg = _("failed to store record\n");
-  else
-    emsg = NULL;
-  if (NULL != op->as_cb)
-    op->as_cb (op->cls,
-              res,
-              emsg);
-  GNUNET_CONTAINER_DLL_remove (h->op_head,
-                               h->op_tail,
-                               op);
-  free_op (op);
-
-}
-
-
-/**
- * Handle an incoming message of type
- * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT
- *
- * @param cls
- * @param msg the message we received
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
- */
-static int
-check_consume_ticket_result (void *cls,
-                             const struct ConsumeTicketResultMessage *msg)
-{
-  size_t msg_len;
-  size_t attrs_len;
-
-  msg_len = ntohs (msg->header.size);
-  attrs_len = ntohs (msg->attrs_len);
-  if (msg_len != sizeof (struct ConsumeTicketResultMessage) + attrs_len)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Handle an incoming message of type
- * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT
- *
- * @param cls
- * @param msg the message we received
- */
-static void
-handle_consume_ticket_result (void *cls,
-                              const struct ConsumeTicketResultMessage *msg)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
-  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
-  size_t attrs_len;
-  uint32_t r_id = ntohl (msg->id);
-
-  attrs_len = ntohs (msg->attrs_len);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Processing attribute result.\n");
-
-
-  for (op = h->op_head; NULL != op; op = op->next)
-    if (op->r_id == r_id)
-      break;
-  if (NULL == op)
-    return;
-
-  {
-    struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
-    struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-    attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&msg[1],
-                                        attrs_len);
-    if (NULL != op->ar_cb)
-    {
-      if (NULL == attrs)
-      {
-        op->ar_cb (op->cls,
-                   &msg->identity,
-                   NULL);
-      }
-      else
-      {
-        for (le = attrs->list_head; NULL != le; le = le->next)
-          op->ar_cb (op->cls,
-                     &msg->identity,
-                     le->claim);
-        GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs);
-      }
-    }
-    if (NULL != op)
-    {
-      op->ar_cb (op->cls,
-                 NULL,
-                 NULL);
-      GNUNET_CONTAINER_DLL_remove (h->op_head,
-                                   h->op_tail,
-                                   op);
-      free_op (op);
-    }
-    return;
-  }
-  GNUNET_assert (0);
-}
-
-
-/**
- * Handle an incoming message of type
- * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT
- *
- * @param cls
- * @param msg the message we received
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
- */
-static int
-check_attribute_result (void *cls,
-                        const struct AttributeResultMessage *msg)
-{
-  size_t msg_len;
-  size_t attr_len;
-
-  msg_len = ntohs (msg->header.size);
-  attr_len = ntohs (msg->attr_len);
-  if (msg_len != sizeof (struct AttributeResultMessage) + attr_len)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Handle an incoming message of type
- * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT
- *
- * @param cls
- * @param msg the message we received
- */
-static void
-handle_attribute_result (void *cls,
-                         const struct AttributeResultMessage *msg)
-{
-  static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
-  struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
-  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it;
-  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
-  size_t attr_len;
-  uint32_t r_id = ntohl (msg->id);
-
-  attr_len = ntohs (msg->attr_len);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Processing attribute result.\n");
-
-
-  for (it = h->it_head; NULL != it; it = it->next)
-    if (it->r_id == r_id)
-      break;
-  for (op = h->op_head; NULL != op; op = op->next)
-    if (op->r_id == r_id)
-      break;
-  if ((NULL == it) && (NULL == op))
-    return;
-
-  if ( (0 == (memcmp (&msg->identity,
-                      &identity_dummy,
-                      sizeof (identity_dummy)))) )
-  {
-    if ((NULL == it) && (NULL == op))
-    {
-      GNUNET_break (0);
-      force_reconnect (h);
-      return;
-    }
-    if (NULL != it)
-    {
-      if (NULL != it->finish_cb)
-        it->finish_cb (it->finish_cb_cls);
-      free_it (it);
-    }
-    if (NULL != op)
-    {
-      if (NULL != op->ar_cb)
-        op->ar_cb (op->cls,
-                   NULL,
-                   NULL);
-      GNUNET_CONTAINER_DLL_remove (h->op_head,
-                                   h->op_tail,
-                                   op);
-      free_op (op);
-
-    }
-    return;
-  }
-
-  {
-    struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
-    attr = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&msg[1],
-                                                  attr_len);
-    if (NULL != it)
-    {
-      if (NULL != it->proc)
-        it->proc (it->proc_cls,
-                  &msg->identity,
-                  attr);
-    } else if (NULL != op)
-    {
-      if (NULL != op->ar_cb)
-        op->ar_cb (op->cls,
-                   &msg->identity,
-                   attr);
-
-    }
-    GNUNET_free (attr);
-    return;
-  }
-  GNUNET_assert (0);
-}
-
-/**
- * Handle an incoming message of type
- * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
- *
- * @param cls
- * @param msg the message we received
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
- */
-static int
-check_ticket_result (void *cls,
-                     const struct TicketResultMessage *msg)
-{
-  size_t msg_len;
-
-  msg_len = ntohs (msg->header.size);
-  if (msg_len < sizeof (struct TicketResultMessage))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-
-
-/**
- * Handle an incoming message of type
- * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
- *
- * @param cls
- * @param msg the message we received
- */
-static void
-handle_ticket_result (void *cls,
-                      const struct TicketResultMessage *msg)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls;
-  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
-  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
-  const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
-  uint32_t r_id = ntohl (msg->id);
-  size_t msg_len;
-
-  for (op = handle->op_head; NULL != op; op = op->next)
-    if (op->r_id == r_id)
-      break;
-  for (it = handle->ticket_it_head; NULL != it; it = it->next)
-    if (it->r_id == r_id)
-      break;
-  if ((NULL == op) && (NULL == it))
-    return;
-  msg_len = ntohs (msg->header.size);
-  if (NULL != op)
-  {
-    GNUNET_CONTAINER_DLL_remove (handle->op_head,
-                                 handle->op_tail,
-                                 op);
-    if (msg_len == sizeof (struct TicketResultMessage))
-    {
-      if (NULL != op->tr_cb)
-        op->tr_cb (op->cls, NULL);
-    } else {
-      ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1];
-      if (NULL != op->tr_cb)
-        op->tr_cb (op->cls, ticket);
-    }
-    free_op (op);
-    return;
-  } else if (NULL != it) {
-    if (msg_len == sizeof (struct TicketResultMessage))
-    {
-      if (NULL != it->tr_cb)
-        GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head,
-                                     handle->ticket_it_tail,
-                                     it);
-      it->finish_cb (it->finish_cb_cls);
-      GNUNET_free (it);
-    } else {
-      ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1];
-      if (NULL != it->tr_cb)
-        it->tr_cb (it->cls, ticket);
-    }
-    return;
-  }
-  GNUNET_break (0);
-}
-
-
-/**
- * Handle an incoming message of type
- * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT
- *
- * @param cls
- * @param msg the message we received
- */
-static void
-handle_revoke_ticket_result (void *cls,
-                             const struct RevokeTicketResultMessage *msg)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
-  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
-  uint32_t r_id = ntohl (msg->id);
-  int32_t success;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Processing revocation result.\n");
-
-
-  for (op = h->op_head; NULL != op; op = op->next)
-    if (op->r_id == r_id)
-      break;
-  if (NULL == op)
-    return;
-  success = ntohl (msg->success);
-  {
-    if (NULL != op->rvk_cb)
-    {
-      op->rvk_cb (op->cls,
-                  success,
-                  NULL);
-    }
-    GNUNET_CONTAINER_DLL_remove (h->op_head,
-                                 h->op_tail,
-                                 op);
-    free_op (op);
-    return;
-  }
-  GNUNET_assert (0);
-}
-
-
-
-/**
- * Try again to connect to the service.
- *
- * @param h handle to the identity provider service.
- */
-static void
-reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
-{
-  struct GNUNET_MQ_MessageHandler handlers[] = {
-    GNUNET_MQ_hd_fixed_size (attribute_store_response,
-                             GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE,
-                             struct AttributeStoreResultMessage,
-                             h),
-    GNUNET_MQ_hd_var_size (attribute_result,
-                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT,
-                           struct AttributeResultMessage,
-                           h),
-    GNUNET_MQ_hd_var_size (ticket_result,
-                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT,
-                           struct TicketResultMessage,
-                           h),
-    GNUNET_MQ_hd_var_size (consume_ticket_result,
-                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT,
-                           struct ConsumeTicketResultMessage,
-                           h),
-    GNUNET_MQ_hd_fixed_size (revoke_ticket_result,
-                             GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT,
-                             struct RevokeTicketResultMessage,
-                             h),
-    GNUNET_MQ_handler_end ()
-  };
-  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
-
-  GNUNET_assert (NULL == h->mq);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Connecting to identity provider service.\n");
-
-  h->mq = GNUNET_CLIENT_connect (h->cfg,
-                                 "identity-provider",
-                                 handlers,
-                                 &mq_error_handler,
-                                 h);
-  if (NULL == h->mq)
-    return;
-  for (op = h->op_head; NULL != op; op = op->next)
-    GNUNET_MQ_send_copy (h->mq,
-                         op->env);
-}
-
-
-/**
- * Connect to the identity provider service.
- *
- * @param cfg the configuration to use
- * @return handle to use
- */
-struct GNUNET_IDENTITY_PROVIDER_Handle *
-GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Handle *h;
-
-  h = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Handle);
-  h->cfg = cfg;
-  reconnect (h);
-  if (NULL == h->mq)
-  {
-    GNUNET_free (h);
-    return NULL;
-  }
-  return h;
-}
-
-
-/**
- * Cancel an operation. Note that the operation MAY still
- * be executed; this merely cancels the continuation; if the request
- * was already transmitted, the service may still choose to complete
- * the operation.
- *
- * @param op operation to cancel
- */
-void
-GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Handle *h = op->h;
-
-  GNUNET_CONTAINER_DLL_remove (h->op_head,
-                               h->op_tail,
-                               op);
-  free_op (op);
-}
-
-
-/**
- * Disconnect from service
- *
- * @param h handle to destroy
- */
-void
-GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
-{
-  GNUNET_assert (NULL != h);
-  if (NULL != h->mq)
-  {
-    GNUNET_MQ_destroy (h->mq);
-    h->mq = NULL;
-  }
-  if (NULL != h->reconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (h->reconnect_task);
-    h->reconnect_task = NULL;
-  }
-  GNUNET_assert (NULL == h->op_head);
-  GNUNET_free (h);
-}
-
-/**
- * Store an attribute.  If the attribute is already present,
- * it is replaced with the new attribute.
- *
- * @param h handle to the identity provider
- * @param pkey private key of the identity
- * @param attr the attribute value
- * @param exp_interval the relative expiration interval for the attribute
- * @param cont continuation to call when done
- * @param cont_cls closure for @a cont
- * @return handle to abort the request
- */
-struct GNUNET_IDENTITY_PROVIDER_Operation *
-GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
-                                          const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
-                                          const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
-                                          const struct GNUNET_TIME_Relative *exp_interval,
-                                          GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont,
-                                          void *cont_cls)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
-  struct AttributeStoreMessage *sam;
-  size_t attr_len;
-
-  op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
-  op->h = h;
-  op->as_cb = cont;
-  op->cls = cont_cls;
-  op->r_id = h->r_id_gen++;
-  GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
-                                    h->op_tail,
-                                    op);
-  attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (attr);
-  op->env = GNUNET_MQ_msg_extra (sam,
-                                 attr_len,
-                                 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE);
-  sam->identity = *pkey;
-  sam->id = htonl (op->r_id);
-  sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
-
-  GNUNET_IDENTITY_ATTRIBUTE_serialize (attr,
-                                       (char*)&sam[1]);
-
-  sam->attr_len = htons (attr_len);
-  if (NULL != h->mq)
-    GNUNET_MQ_send_copy (h->mq,
-                         op->env);
-  return op;
-
-}
-
-
-/**
- * List all attributes for a local identity.
- * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle`
- * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and
- * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once
- * immediately, and then again after
- * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked.
- *
- * On error (disconnect), @a error_cb will be invoked.
- * On normal completion, @a finish_cb proc will be
- * invoked.
- *
- * @param h handle to the idp
- * @param identity identity to access
- * @param error_cb function to call on error (i.e. disconnect),
- *        the handle is afterwards invalid
- * @param error_cb_cls closure for @a error_cb
- * @param proc function to call on each attribute; it
- *        will be called repeatedly with a value (if available)
- * @param proc_cls closure for @a proc
- * @param finish_cb function to call on completion
- *        the handle is afterwards invalid
- * @param finish_cb_cls closure for @a finish_cb
- * @return an iterator handle to use for iteration
- */
-struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *
-GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
-                                               const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
-                                               GNUNET_SCHEDULER_TaskCallback error_cb,
-                                               void *error_cb_cls,
-                                               GNUNET_IDENTITY_PROVIDER_AttributeResult proc,
-                                               void *proc_cls,
-                                               GNUNET_SCHEDULER_TaskCallback finish_cb,
-                                               void *finish_cb_cls)
-{
-  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it;
-  struct GNUNET_MQ_Envelope *env;
-  struct AttributeIterationStartMessage *msg;
-  uint32_t rid;
-
-  rid = h->r_id_gen++;
-  it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator);
-  it->h = h;
-  it->error_cb = error_cb;
-  it->error_cb_cls = error_cb_cls;
-  it->finish_cb = finish_cb;
-  it->finish_cb_cls = finish_cb_cls;
-  it->proc = proc;
-  it->proc_cls = proc_cls;
-  it->r_id = rid;
-  it->identity = *identity;
-  GNUNET_CONTAINER_DLL_insert_tail (h->it_head,
-                                    h->it_tail,
-                                    it);
-  env = GNUNET_MQ_msg (msg,
-                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START);
-  msg->id = htonl (rid);
-  msg->identity = *identity;
-  if (NULL == h->mq)
-    it->env = env;
-  else
-    GNUNET_MQ_send (h->mq,
-                    env);
-  return it;
-}
-
-
-/**
- * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start
- * for the next record.
- *
- * @param it the iterator
- */
-void
-GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
-  struct AttributeIterationNextMessage *msg;
-  struct GNUNET_MQ_Envelope *env;
-
-  env = GNUNET_MQ_msg (msg,
-                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT);
-  msg->id = htonl (it->r_id);
-  GNUNET_MQ_send (h->mq,
-                  env);
-}
-
-
-/**
- * Stops iteration and releases the idp handle for further calls.  Must
- * be called on any iteration that has not yet completed prior to calling
- * #GNUNET_IDENTITY_PROVIDER_disconnect.
- *
- * @param it the iterator
- */
-void
-GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
-  struct GNUNET_MQ_Envelope *env;
-  struct AttributeIterationStopMessage *msg;
-
-  if (NULL != h->mq)
-  {
-    env = GNUNET_MQ_msg (msg,
-                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP);
-    msg->id = htonl (it->r_id);
-    GNUNET_MQ_send (h->mq,
-                    env);
-  }
-  free_it (it);
-}
-
-
-/** TODO
- * Issues a ticket to another identity. The identity may use
- * @GNUNET_IDENTITY_PROVIDER_authorization_ticket_consume to consume the ticket
- * and retrieve the attributes specified in the AttributeList.
- *
- * @param h the identity provider to use
- * @param iss the issuing identity
- * @param rp the subject of the ticket (the relying party)
- * @param attrs the attributes that the relying party is given access to
- * @param cb the callback
- * @param cb_cls the callback closure
- * @return handle to abort the operation
- */
-struct GNUNET_IDENTITY_PROVIDER_Operation *
-GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
-                                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
-                                       const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
-                                       const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
-                                       GNUNET_IDENTITY_PROVIDER_TicketCallback cb,
-                                       void *cb_cls)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
-  struct IssueTicketMessage *tim;
-  size_t attr_len;
-
-  op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
-  op->h = h;
-  op->tr_cb = cb;
-  op->cls = cb_cls;
-  op->r_id = h->r_id_gen++;
-  GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
-                                    h->op_tail,
-                                    op);
-  attr_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs);
-  op->env = GNUNET_MQ_msg_extra (tim,
-                                 attr_len,
-                                 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET);
-  tim->identity = *iss;
-  tim->rp = *rp;
-  tim->id = htonl (op->r_id);
-
-  GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs,
-                                            (char*)&tim[1]);
-
-  tim->attr_len = htons (attr_len);
-  if (NULL != h->mq)
-    GNUNET_MQ_send_copy (h->mq,
-                         op->env);
-  return op;
-}
-
-/**
- * Consumes an issued ticket. The ticket is persisted
- * and used to retrieve identity information from the issuer
- *
- * @param h the identity provider to use
- * @param identity the identity that is the subject of the issued ticket (the relying party)
- * @param ticket the issued ticket to consume
- * @param cb the callback to call
- * @param cb_cls the callback closure
- * @return handle to abort the operation
- */
-struct GNUNET_IDENTITY_PROVIDER_Operation *
-GNUNET_IDENTITY_PROVIDER_ticket_consume (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
-                                         const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
-                                         const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                                         GNUNET_IDENTITY_PROVIDER_AttributeResult cb,
-                                         void *cb_cls)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
-  struct ConsumeTicketMessage *ctm;
-
-  op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
-  op->h = h;
-  op->ar_cb = cb;
-  op->cls = cb_cls;
-  op->r_id = h->r_id_gen++;
-  GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
-                                    h->op_tail,
-                                    op);
-  op->env = GNUNET_MQ_msg_extra (ctm,
-                                 sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket),
-                                 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET);
-  ctm->identity = *identity;
-  ctm->id = htonl (op->r_id);
-
-  GNUNET_memcpy ((char*)&ctm[1],
-                 ticket,
-                 sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket));
-
-  if (NULL != h->mq)
-    GNUNET_MQ_send_copy (h->mq,
-                         op->env);
-  return op;
-
-}
-
-
-/**
- * Lists all tickets that have been issued to remote
- * identites (relying parties)
- *
- * @param h the identity provider to use
- * @param identity the issuing identity
- * @param error_cb function to call on error (i.e. disconnect),
- *        the handle is afterwards invalid
- * @param error_cb_cls closure for @a error_cb
- * @param proc function to call on each ticket; it
- *        will be called repeatedly with a value (if available)
- * @param proc_cls closure for @a proc
- * @param finish_cb function to call on completion
- *        the handle is afterwards invalid
- * @param finish_cb_cls closure for @a finish_cb
- * @return an iterator handle to use for iteration
- */
-struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
-GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
-                                                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
-                                                 GNUNET_SCHEDULER_TaskCallback error_cb,
-                                                 void *error_cb_cls,
-                                                 GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
-                                                 void *proc_cls,
-                                                 GNUNET_SCHEDULER_TaskCallback finish_cb,
-                                                 void *finish_cb_cls)
-{
-  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
-  struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
-  struct GNUNET_MQ_Envelope *env;
-  struct TicketIterationStartMessage *msg;
-  uint32_t rid;
-
-  GNUNET_CRYPTO_ecdsa_key_get_public (identity,
-                                      &identity_pub);
-  rid = h->r_id_gen++;
-  it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator);
-  it->h = h;
-  it->error_cb = error_cb;
-  it->error_cb_cls = error_cb_cls;
-  it->finish_cb = finish_cb;
-  it->finish_cb_cls = finish_cb_cls;
-  it->tr_cb = proc;
-  it->cls = proc_cls;
-  it->r_id = rid;
-  GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head,
-                                    h->ticket_it_tail,
-                                    it);
-  env = GNUNET_MQ_msg (msg,
-                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START);
-  msg->id = htonl (rid);
-  msg->identity = identity_pub;
-  msg->is_audience = htonl (GNUNET_NO);
-  if (NULL == h->mq)
-    it->env = env;
-  else
-    GNUNET_MQ_send (h->mq,
-                    env);
-  return it;
-
-}
-
-
-/**
- * Lists all tickets that have been issued to remote
- * identites (relying parties)
- *
- * @param h the identity provider to use
- * @param identity the issuing identity
- * @param error_cb function to call on error (i.e. disconnect),
- *        the handle is afterwards invalid
- * @param error_cb_cls closure for @a error_cb
- * @param proc function to call on each ticket; it
- *        will be called repeatedly with a value (if available)
- * @param proc_cls closure for @a proc
- * @param finish_cb function to call on completion
- *        the handle is afterwards invalid
- * @param finish_cb_cls closure for @a finish_cb
- * @return an iterator handle to use for iteration
- */
-struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
-GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
-                                                    const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-                                                    GNUNET_SCHEDULER_TaskCallback error_cb,
-                                                    void *error_cb_cls,
-                                                    GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
-                                                    void *proc_cls,
-                                                    GNUNET_SCHEDULER_TaskCallback finish_cb,
-                                                    void *finish_cb_cls)
-{
-  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
-  struct GNUNET_MQ_Envelope *env;
-  struct TicketIterationStartMessage *msg;
-  uint32_t rid;
-
-  rid = h->r_id_gen++;
-  it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator);
-  it->h = h;
-  it->error_cb = error_cb;
-  it->error_cb_cls = error_cb_cls;
-  it->finish_cb = finish_cb;
-  it->finish_cb_cls = finish_cb_cls;
-  it->tr_cb = proc;
-  it->cls = proc_cls;
-  it->r_id = rid;
-  GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head,
-                                    h->ticket_it_tail,
-                                    it);
-  env = GNUNET_MQ_msg (msg,
-                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START);
-  msg->id = htonl (rid);
-  msg->identity = *identity;
-  msg->is_audience = htonl (GNUNET_YES);
-  if (NULL == h->mq)
-    it->env = env;
-  else
-    GNUNET_MQ_send (h->mq,
-                    env);
-  return it;
-
-
-}
-
-/**
- * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start
- * for the next record.
- *
- * @param it the iterator
- */
-void
-GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
-  struct TicketIterationNextMessage *msg;
-  struct GNUNET_MQ_Envelope *env;
-
-  env = GNUNET_MQ_msg (msg,
-                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT);
-  msg->id = htonl (it->r_id);
-  GNUNET_MQ_send (h->mq,
-                  env);
-}
-
-
-/**
- * Stops iteration and releases the idp handle for further calls.  Must
- * be called on any iteration that has not yet completed prior to calling
- * #GNUNET_IDENTITY_PROVIDER_disconnect.
- *
- * @param it the iterator
- */
-void
-GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
-  struct GNUNET_MQ_Envelope *env;
-  struct TicketIterationStopMessage *msg;
-
-  if (NULL != h->mq)
-  {
-    env = GNUNET_MQ_msg (msg,
-                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP);
-    msg->id = htonl (it->r_id);
-    GNUNET_MQ_send (h->mq,
-                    env);
-  }
-  GNUNET_free (it);
-}
-
-/**
- * Revoked an issued ticket. The relying party will be unable to retrieve
- * updated attributes.
- *
- * @param h the identity provider to use
- * @param identity the issuing identity
- * @param ticket the ticket to revoke
- * @param cb the callback
- * @param cb_cls the callback closure
- * @return handle to abort the operation
- */
-struct GNUNET_IDENTITY_PROVIDER_Operation *
-GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
-                                        const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
-                                        const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                                        GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb,
-                                        void *cb_cls)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
-  struct RevokeTicketMessage *msg;
-  uint32_t rid;
-
-  rid = h->r_id_gen++;
-  op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
-  op->h = h;
-  op->rvk_cb = cb;
-  op->cls = cb_cls;
-  op->r_id = rid;
-  GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
-                                    h->op_tail,
-                                    op);
-  op->env = GNUNET_MQ_msg_extra (msg,
-                             sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
-                             GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET);
-  msg->id = htonl (rid);
-  msg->identity = *identity;
-  GNUNET_memcpy (&msg[1],
-                 ticket,
-                 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
-  if (NULL != h->mq) {
-    GNUNET_MQ_send (h->mq,
-                    op->env);
-    op->env = NULL;
-  }
-  return op;
-}
-
-
-
-/* end of identity_provider_api.c */
diff --git a/src/identity-provider/jwt.c b/src/identity-provider/jwt.c
deleted file mode 100644 (file)
index 7ac4f00..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
-      This file is part of GNUnet
-      Copyright (C) 2010-2015 GNUnet e.V.
-
-      GNUnet is free software: you can redistribute it and/or modify it
-      under the terms of the GNU Affero General Public License as published
-      by the Free Software Foundation, either version 3 of the License,
-      or (at your option) any later version.
-
-      GNUnet is distributed in the hope that it will be useful, but
-      WITHOUT ANY WARRANTY; without even the implied warranty of
-      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-      Affero General Public License for more details.
-     
-      You should have received a copy of the GNU Affero General Public License
-      along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * @file identity-provider/jwt.c
- * @brief helper library for JSON-Web-Tokens
- * @author Martin Schanzenbach
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_signatures.h"
-#include "gnunet_identity_attribute_lib.h"
-#include <jansson.h>
-
-
-#define JWT_ALG "alg"
-
-/* Use 512bit HMAC */
-#define JWT_ALG_VALUE "HS512"
-
-#define JWT_TYP "typ"
-
-#define JWT_TYP_VALUE "jwt"
-
-#define SERVER_ADDRESS "https://reclaim.id/api/openid/userinfo"
-
-static char*
-create_jwt_header(void)
-{
-  json_t *root;
-  char *json_str;
-
-  root = json_object ();
-  json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
-  json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
-
-  json_str = json_dumps (root, JSON_INDENT(1));
-  json_decref (root);
-  return json_str;
-}
-
-/**
- * Create a JWT from attributes
- *
- * @param aud_key the public of the subject
- * @param attrs the attribute list
- * @param priv_key the key used to sign the JWT
- * @return a new base64-encoded JWT string.
- */
-char*
-jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-                      const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
-                                                const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
-                                                const struct GNUNET_CRYPTO_AuthKey *priv_key)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-  struct GNUNET_HashCode signature;
-  char* audience;
-  char* subject;
-  char* header;
-  char* padding;
-  char* body_str;
-  char* result;
-  char* header_base64;
-  char* body_base64;
-  char* signature_target;
-  char* signature_base64;
-  char* attr_val_str;
-  json_t* body;
-
-  //exp REQUIRED time expired from config
-  //iat REQUIRED time now
-  //auth_time only if max_age
-  //nonce only if nonce
-  // OPTIONAL acr,amr,azp
-  subject = GNUNET_STRINGS_data_to_string_alloc (&sub_key,
-                                                sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  audience = GNUNET_STRINGS_data_to_string_alloc (aud_key,
-                                                  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  header = create_jwt_header ();
-  body = json_object ();
-  
-  //iss REQUIRED case sensitive server uri with https
-  //The issuer is the local reclaim instance (e.g. https://reclaim.id/api/openid)
-  json_object_set_new (body,
-                       "iss", json_string (SERVER_ADDRESS));
-  //sub REQUIRED public key identity, not exceed 255 ASCII  length
-  json_object_set_new (body,
-                       "sub", json_string (subject));
-  //aud REQUIRED public key client_id must be there
-  json_object_set_new (body,
-                       "aud", json_string (audience));
-  for (le = attrs->list_head; NULL != le; le = le->next)
-  {
-    attr_val_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (le->claim->type,
-                                                              le->claim->data,
-                                                              le->claim->data_size);
-    json_object_set_new (body,
-                         le->claim->name,
-                         json_string (attr_val_str));
-    GNUNET_free (attr_val_str);
-  }
-  body_str = json_dumps (body, JSON_INDENT(0));
-  json_decref (body);
-
-  GNUNET_STRINGS_base64_encode (header,
-                                strlen (header),
-                                &header_base64);
-  //Remove GNUNET padding of base64
-  padding = strtok(header_base64, "=");
-  while (NULL != padding)
-    padding = strtok(NULL, "=");
-
-  GNUNET_STRINGS_base64_encode (body_str,
-                                strlen (body_str),
-                                &body_base64);
-
-  //Remove GNUNET padding of base64
-  padding = strtok(body_base64, "=");
-  while (NULL != padding)
-    padding = strtok(NULL, "=");
-
-  GNUNET_free (subject);
-  GNUNET_free (audience);
-
-  /**
-   * Creating the JWT signature. This might not be
-   * standards compliant, check.
-   */
-  GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64);
-  GNUNET_CRYPTO_hmac (priv_key, signature_target, strlen (signature_target), &signature);
-  GNUNET_STRINGS_base64_encode ((const char*)&signature,
-                                sizeof (struct GNUNET_HashCode),
-                                &signature_base64);
-  GNUNET_asprintf (&result, "%s.%s.%s",
-                   header_base64, body_base64, signature_base64);
-
-  GNUNET_free (signature_target);
-  GNUNET_free (header);
-  GNUNET_free (body_str);
-  GNUNET_free (signature_base64);
-  GNUNET_free (body_base64);
-  GNUNET_free (header_base64);
-  return result;
-}
diff --git a/src/identity-provider/jwt.h b/src/identity-provider/jwt.h
deleted file mode 100644 (file)
index 80b6caa..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef JWT_H
-#define JWT_H
-
-char*
-jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-                      const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
-                                                const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
-                                                const struct GNUNET_CRYPTO_AuthKey *priv_key);
-
-#endif
diff --git a/src/identity-provider/plugin_gnsrecord_identity_provider.c b/src/identity-provider/plugin_gnsrecord_identity_provider.c
deleted file mode 100644 (file)
index f0dc563..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
-     This file is part of GNUnet
-     Copyright (C) 2013, 2014 GNUnet e.V.
-
-     GNUnet is free software: you can redistribute it and/or modify it
-     under the terms of the GNU Affero General Public License as published
-     by the Free Software Foundation, either version 3 of the License,
-     or (at your option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     Affero General Public License for more details.
-    
-     You should have received a copy of the GNU Affero General Public License
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file identity-provider/plugin_gnsrecord_identity_provider.c
- * @brief gnsrecord plugin to provide the API for identity records
- * @author Martin Schanzenbach
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_gnsrecord_lib.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 *
-value_to_string (void *cls,
-                 uint32_t type,
-                 const void *data,
-                 size_t data_size)
-{
-  const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
-  const struct GNUNET_CRYPTO_EcdsaPublicKey *audience_pubkey;
-  const char *scopes;
-  char *ecdhe_str;
-  char *aud_str;
-  char *result;
-
-  switch (type)
-  {
-    case GNUNET_GNSRECORD_TYPE_ID_ATTR:
-      return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
-    case GNUNET_GNSRECORD_TYPE_ID_TOKEN: //DEPRECATED
-      return GNUNET_strndup (data, data_size);
-    case GNUNET_GNSRECORD_TYPE_ABE_KEY:
-    case GNUNET_GNSRECORD_TYPE_ABE_MASTER:
-      return GNUNET_STRINGS_data_to_string_alloc (data, data_size); 
-    case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: //DEPRECATED
-        ecdhe_privkey = data;
-        audience_pubkey = data+sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
-        scopes =  (char*) audience_pubkey+(sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-        ecdhe_str = GNUNET_STRINGS_data_to_string_alloc (ecdhe_privkey,
-                                                        sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
-        aud_str = GNUNET_STRINGS_data_to_string_alloc (audience_pubkey,
-                                                       sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-        GNUNET_asprintf (&result,
-                         "%s;%s;%s",
-                         ecdhe_str, aud_str, scopes);
-        GNUNET_free (aud_str);
-        GNUNET_free (ecdhe_str);
-        return result;
-
-    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
-string_to_value (void *cls,
-                 uint32_t type,
-                 const char *s,
-                 void **data,
-                 size_t *data_size)
-{
-  char* ecdhe_str;
-  char* aud_keystr;
-  char* write_ptr;
-  char* tmp_tok;
-  char* str;
-
-  if (NULL == s)
-    return GNUNET_SYSERR;
-  switch (type)
-  {
-    case GNUNET_GNSRECORD_TYPE_ID_ATTR:
-      return GNUNET_STRINGS_string_to_data (s,
-                                            strlen (s),
-                                            *data,
-                                            *data_size);
-    case GNUNET_GNSRECORD_TYPE_ID_TOKEN:
-      *data = GNUNET_strdup (s);
-      *data_size = strlen (s);
-      return GNUNET_OK;
-    case GNUNET_GNSRECORD_TYPE_ABE_KEY:
-    case GNUNET_GNSRECORD_TYPE_ABE_MASTER:
-      return GNUNET_STRINGS_string_to_data (s,
-                                            strlen (s),
-                                            *data,
-                                            *data_size);
-    case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA:
-      tmp_tok = GNUNET_strdup (s);
-      ecdhe_str = strtok (tmp_tok, ";");
-      if (NULL == ecdhe_str)
-      {
-        GNUNET_free (tmp_tok);
-        return GNUNET_SYSERR;
-      }
-      aud_keystr = strtok (NULL, ";");
-      if (NULL == aud_keystr)
-      {
-        GNUNET_free (tmp_tok);
-        return GNUNET_SYSERR;
-      }
-      str = strtok (NULL, ";");
-      if (NULL == str)
-      {
-        GNUNET_free (tmp_tok);
-        return GNUNET_SYSERR;
-      }
-      *data_size = strlen (str) + 1
-        +sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
-        +sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
-      *data = GNUNET_malloc (*data_size);
-
-      write_ptr = *data;
-      GNUNET_STRINGS_string_to_data (ecdhe_str,
-                                     strlen (ecdhe_str),
-                                     write_ptr,
-                                     sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
-      write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
-      GNUNET_STRINGS_string_to_data (aud_keystr,
-                                     strlen (aud_keystr),
-                                     write_ptr,
-                                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-      write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
-      GNUNET_memcpy (write_ptr, str, strlen (str) + 1); //with 0-Terminator
-      GNUNET_free (tmp_tok);
-      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[] = {
-  { "ID_ATTR", GNUNET_GNSRECORD_TYPE_ID_ATTR },
-  { "ID_TOKEN", GNUNET_GNSRECORD_TYPE_ID_TOKEN },
-  { "ABE_KEY", GNUNET_GNSRECORD_TYPE_ABE_KEY },
-  { "ABE_MASTER", GNUNET_GNSRECORD_TYPE_ABE_MASTER },
-  { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA },
-  { NULL, UINT32_MAX }
-};
-
-
-/**
- * Convert a type name (i.e. "AAAA") to the corresponding number.
- *
- * @param cls closure, unused
- * @param dns_typename name to convert
- * @return corresponding number, UINT32_MAX on error
- */
-static uint32_t
-typename_to_number (void *cls,
-                    const char *dns_typename)
-{
-  unsigned int i;
-
-  i=0;
-  while ( (NULL != name_map[i].name) &&
-          (0 != strcasecmp (dns_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 *
-number_to_typename (void *cls,
-                    uint32_t type)
-{
-  unsigned int i;
-
-  i=0;
-  while ( (NULL != name_map[i].name) &&
-          (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_identity_provider_init (void *cls)
-{
-  struct GNUNET_GNSRECORD_PluginFunctions *api;
-
-  api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
-  api->value_to_string = &value_to_string;
-  api->string_to_value = &string_to_value;
-  api->typename_to_number = &typename_to_number;
-  api->number_to_typename = &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_identity_provider_done (void *cls)
-{
-  struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
-
-  GNUNET_free (api);
-  return NULL;
-}
-
-/* end of plugin_gnsrecord_dns.c */
diff --git a/src/identity-provider/plugin_identity_provider_sqlite.c b/src/identity-provider/plugin_identity_provider_sqlite.c
deleted file mode 100644 (file)
index f2a8b7b..0000000
+++ /dev/null
@@ -1,734 +0,0 @@
- /*
-  * This file is part of GNUnet
-  * Copyright (C) 2009-2017 GNUnet e.V.
-  *
-  * GNUnet is free software: you can redistribute it and/or modify it
-  * under the terms of the GNU Affero General Public License as published
-  * by the Free Software Foundation, either version 3 of the License,
-  * or (at your option) any later version.
-  *
-  * GNUnet is distributed in the hope that it will be useful, but
-  * WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  * Affero General Public License for more details.
-  *
-  * You should have received a copy of the GNU Affero General Public License
-  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  */
-
-/**
- * @file identity-provider/plugin_identity_provider_sqlite.c
- * @brief sqlite-based idp backend
- * @author Martin Schanzenbach
- */
-
-#include "platform.h"
-#include "gnunet_identity_provider_service.h"
-#include "gnunet_identity_provider_plugin.h"
-#include "gnunet_identity_attribute_lib.h"
-#include "gnunet_sq_lib.h"
-#include <sqlite3.h>
-
-/**
- * After how many ms "busy" should a DB operation fail for good?  A
- * low value makes sure that we are more responsive to requests
- * (especially PUTs).  A high value guarantees a higher success rate
- * (SELECTs in iterate can take several seconds despite LIMIT=1).
- *
- * The default value of 1s should ensure that users do not experience
- * huge latencies while at the same time allowing operations to
- * succeed with reasonable probability.
- */
-#define BUSY_TIMEOUT_MS 1000
-
-
-/**
- * Log an error message at log-level 'level' that indicates
- * a failure of the command 'cmd' on file 'filename'
- * with the message given by strerror(errno).
- */
-#define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "identity-provider", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
-
-#define LOG(kind,...) GNUNET_log_from (kind, "identity-provider-sqlite", __VA_ARGS__)
-
-
-/**
- * Context for all functions in this plugin.
- */
-struct Plugin
-{
-
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Database filename.
-   */
-  char *fn;
-
-  /**
-   * Native SQLite database handle.
-   */
-  sqlite3 *dbh;
-
-  /**
-   * Precompiled SQL to store ticket.
-   */
-  sqlite3_stmt *store_ticket;
-
-  /**
-   * Precompiled SQL to delete existing ticket.
-   */
-  sqlite3_stmt *delete_ticket;
-
-  /**
-   * Precompiled SQL to iterate tickets.
-   */
-  sqlite3_stmt *iterate_tickets;
-
-  /**
-   * Precompiled SQL to get ticket attributes.
-   */
-  sqlite3_stmt *get_ticket_attrs;
-  
-  /**
-   * Precompiled SQL to iterate tickets by audience.
-   */
-  sqlite3_stmt *iterate_tickets_by_audience;
-};
-
-
-/**
- * @brief Prepare a SQL statement
- *
- * @param dbh handle to the database
- * @param zSql SQL statement, UTF-8 encoded
- * @param ppStmt set to the prepared statement
- * @return 0 on success
- */
-static int
-sq_prepare (sqlite3 *dbh,
-            const char *zSql,
-            sqlite3_stmt **ppStmt)
-{
-  char *dummy;
-  int result;
-
-  result =
-      sqlite3_prepare_v2 (dbh,
-                          zSql,
-                          strlen (zSql),
-                          ppStmt,
-                          (const char **) &dummy);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Prepared `%s' / %p: %d\n",
-       zSql,
-       *ppStmt,
-       result);
-  return result;
-}
-
-/**
- * Create our database indices.
- *
- * @param dbh handle to the database
- */
-static void
-create_indices (sqlite3 * dbh)
-{
-  /* create indices */
-  if ( (SQLITE_OK !=
-       sqlite3_exec (dbh,
-                      "CREATE INDEX IF NOT EXISTS identity_reverse ON identity001tickets (identity,audience)",
-                     NULL, NULL, NULL)) ||
-       (SQLITE_OK !=
-       sqlite3_exec (dbh,
-                      "CREATE INDEX IF NOT EXISTS it_iter ON identity001tickets (rnd)",
-                     NULL, NULL, NULL)) )
-    LOG (GNUNET_ERROR_TYPE_ERROR,
-        "Failed to create indices: %s\n",
-         sqlite3_errmsg (dbh));
-}
-
-
-
-#if 0
-#define CHECK(a) GNUNET_break(a)
-#define ENULL NULL
-#else
-#define ENULL &e
-#define ENULL_DEFINED 1
-#define CHECK(a) if (! (a)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); }
-#endif
-
-
-/**
- * Initialize the database connections and associated
- * data structures (create tables and indices
- * as needed as well).
- *
- * @param plugin the plugin context (state for this module)
- * @return #GNUNET_OK on success
- */
-static int
-database_setup (struct Plugin *plugin)
-{
-  sqlite3_stmt *stmt;
-  char *afsdir;
-#if ENULL_DEFINED
-  char *e;
-#endif
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
-                                               "identity-provider-sqlite",
-                                               "FILENAME",
-                                               &afsdir))
-  {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                              "identity-provider-sqlite",
-                               "FILENAME");
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_OK !=
-      GNUNET_DISK_file_test (afsdir))
-  {
-    if (GNUNET_OK !=
-        GNUNET_DISK_directory_create_for_file (afsdir))
-    {
-      GNUNET_break (0);
-      GNUNET_free (afsdir);
-      return GNUNET_SYSERR;
-    }
-  }
-  /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
-  plugin->fn = afsdir;
-
-  /* Open database and precompile statements */
-  if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK)
-  {
-    LOG (GNUNET_ERROR_TYPE_ERROR,
-        _("Unable to initialize SQLite: %s.\n"),
-        sqlite3_errmsg (plugin->dbh));
-    return GNUNET_SYSERR;
-  }
-  CHECK (SQLITE_OK ==
-         sqlite3_exec (plugin->dbh,
-                       "PRAGMA temp_store=MEMORY", NULL, NULL,
-                       ENULL));
-  CHECK (SQLITE_OK ==
-         sqlite3_exec (plugin->dbh,
-                       "PRAGMA synchronous=NORMAL", NULL, NULL,
-                       ENULL));
-  CHECK (SQLITE_OK ==
-         sqlite3_exec (plugin->dbh,
-                       "PRAGMA legacy_file_format=OFF", NULL, NULL,
-                       ENULL));
-  CHECK (SQLITE_OK ==
-         sqlite3_exec (plugin->dbh,
-                       "PRAGMA auto_vacuum=INCREMENTAL", NULL,
-                       NULL, ENULL));
-  CHECK (SQLITE_OK ==
-         sqlite3_exec (plugin->dbh,
-                       "PRAGMA encoding=\"UTF-8\"", NULL,
-                       NULL, ENULL));
-  CHECK (SQLITE_OK ==
-         sqlite3_exec (plugin->dbh,
-                       "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL,
-                       ENULL));
-  CHECK (SQLITE_OK ==
-         sqlite3_exec (plugin->dbh,
-                       "PRAGMA page_size=4092", NULL, NULL,
-                       ENULL));
-
-  CHECK (SQLITE_OK ==
-         sqlite3_busy_timeout (plugin->dbh,
-                               BUSY_TIMEOUT_MS));
-
-
-  /* Create table */
-  CHECK (SQLITE_OK ==
-         sq_prepare (plugin->dbh,
-                     "SELECT 1 FROM sqlite_master WHERE tbl_name = 'identity001tickets'",
-                     &stmt));
-  if ((sqlite3_step (stmt) == SQLITE_DONE) &&
-      (sqlite3_exec
-       (plugin->dbh,
-        "CREATE TABLE identity001tickets ("
-        " identity BLOB NOT NULL DEFAULT '',"
-        " audience BLOB NOT NULL DEFAULT '',"
-             " rnd INT8 NOT NULL DEFAULT '',"
-        " attributes BLOB NOT NULL DEFAULT ''"
-       ")",
-       NULL, NULL, NULL) != SQLITE_OK))
-  {
-    LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR,
-                "sqlite3_exec");
-    sqlite3_finalize (stmt);
-    return GNUNET_SYSERR;
-  }
-  sqlite3_finalize (stmt);
-
-  create_indices (plugin->dbh);
-
-  if ( (SQLITE_OK !=
-        sq_prepare (plugin->dbh,
-                    "INSERT INTO identity001tickets (identity, audience, rnd, attributes)"
-                    " VALUES (?, ?, ?, ?)",
-                    &plugin->store_ticket)) ||
-       (SQLITE_OK !=
-        sq_prepare (plugin->dbh,
-                    "DELETE FROM identity001tickets WHERE identity=? AND rnd=?",
-                    &plugin->delete_ticket)) ||
-       (SQLITE_OK !=
-        sq_prepare (plugin->dbh,
-                    "SELECT identity,audience,rnd,attributes"
-                    " FROM identity001tickets WHERE identity=? AND rnd=?",
-                    &plugin->get_ticket_attrs)) ||
-       (SQLITE_OK !=
-        sq_prepare (plugin->dbh,
-                    "SELECT identity,audience,rnd,attributes"
-                    " FROM identity001tickets WHERE identity=?"
-                    " ORDER BY rnd LIMIT 1 OFFSET ?",
-                    &plugin->iterate_tickets)) ||
-       (SQLITE_OK !=
-        sq_prepare (plugin->dbh,
-                    "SELECT identity,audience,rnd,attributes"
-                    " FROM identity001tickets WHERE audience=?"
-                    " ORDER BY rnd LIMIT 1 OFFSET ?",
-                    &plugin->iterate_tickets_by_audience)) ) 
-  {
-    LOG_SQLITE (plugin,
-                GNUNET_ERROR_TYPE_ERROR,
-                "precompiling");
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Shutdown database connection and associate data
- * structures.
- * @param plugin the plugin context (state for this module)
- */
-static void
-database_shutdown (struct Plugin *plugin)
-{
-  int result;
-  sqlite3_stmt *stmt;
-
-  if (NULL != plugin->store_ticket)
-    sqlite3_finalize (plugin->store_ticket);
-  if (NULL != plugin->delete_ticket)
-    sqlite3_finalize (plugin->delete_ticket);
-  if (NULL != plugin->iterate_tickets)
-    sqlite3_finalize (plugin->iterate_tickets);
-  if (NULL != plugin->iterate_tickets_by_audience)
-    sqlite3_finalize (plugin->iterate_tickets_by_audience);
-  if (NULL != plugin->get_ticket_attrs)
-    sqlite3_finalize (plugin->get_ticket_attrs);
-  result = sqlite3_close (plugin->dbh);
-  if (result == SQLITE_BUSY)
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-        _("Tried to close sqlite without finalizing all prepared statements.\n"));
-    stmt = sqlite3_next_stmt (plugin->dbh,
-                              NULL);
-    while (NULL != stmt)
-    {
-      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
-                       "sqlite",
-                       "Closing statement %p\n",
-                       stmt);
-      result = sqlite3_finalize (stmt);
-      if (result != SQLITE_OK)
-        GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
-                         "sqlite",
-                         "Failed to close statement %p: %d\n",
-                         stmt,
-                         result);
-      stmt = sqlite3_next_stmt (plugin->dbh,
-                                NULL);
-    }
-    result = sqlite3_close (plugin->dbh);
-  }
-  if (SQLITE_OK != result)
-    LOG_SQLITE (plugin,
-                GNUNET_ERROR_TYPE_ERROR,
-                "sqlite3_close");
-
-  GNUNET_free_non_null (plugin->fn);
-}
-
-
-/**
- * Store a ticket in the database.
- *
- * @param cls closure (internal context for the plugin)
- * @param ticket the ticket to persist
- * @param attrs the attributes associated with the ticket
- * @return #GNUNET_OK on success, else #GNUNET_SYSERR
- */
-static int
-identity_provider_sqlite_store_ticket (void *cls,
-                                       const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                                       const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
-{
-  struct Plugin *plugin = cls;
-  size_t attrs_len;
-  char *attrs_ser;
-  int n;
-
-  { 
-    /* First delete duplicates */
-    struct GNUNET_SQ_QueryParam dparams[] = {
-      GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
-      GNUNET_SQ_query_param_uint64 (&ticket->rnd),
-      GNUNET_SQ_query_param_end
-    };
-    if (GNUNET_OK !=
-        GNUNET_SQ_bind (plugin->delete_ticket,
-                        dparams))
-    {
-      LOG_SQLITE (plugin,
-                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
-                  "sqlite3_bind_XXXX");
-      GNUNET_SQ_reset (plugin->dbh,
-                       plugin->delete_ticket);
-      return GNUNET_SYSERR;
-    }
-    n = sqlite3_step (plugin->delete_ticket);
-    GNUNET_SQ_reset (plugin->dbh,
-                     plugin->delete_ticket);
-    
-    attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs);
-    attrs_ser = GNUNET_malloc (attrs_len);
-    GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs,
-                              attrs_ser);
-    struct GNUNET_SQ_QueryParam sparams[] = {
-      GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
-      GNUNET_SQ_query_param_auto_from_type (&ticket->audience),
-      GNUNET_SQ_query_param_uint64 (&ticket->rnd),
-      GNUNET_SQ_query_param_fixed_size (attrs_ser, attrs_len),
-      GNUNET_SQ_query_param_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_SQ_bind (plugin->store_ticket,
-                        sparams))
-    {
-      LOG_SQLITE (plugin,
-                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
-                  "sqlite3_bind_XXXX");
-      GNUNET_SQ_reset (plugin->dbh,
-                       plugin->store_ticket);
-      return GNUNET_SYSERR;
-    }
-    n = sqlite3_step (plugin->store_ticket);
-    GNUNET_SQ_reset (plugin->dbh,
-                     plugin->store_ticket);
-    GNUNET_free (attrs_ser);
-  }
-  switch (n)
-  {
-    case SQLITE_DONE:
-      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
-                       "sqlite",
-                       "Ticket stored\n");
-      return GNUNET_OK;
-    case SQLITE_BUSY:
-      LOG_SQLITE (plugin,
-                  GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
-                  "sqlite3_step");
-      return GNUNET_NO;
-    default:
-      LOG_SQLITE (plugin,
-                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
-                  "sqlite3_step");
-      return GNUNET_SYSERR;
-  }
-}
-
-
-/**
- * Store a ticket in the database.
- *
- * @param cls closure (internal context for the plugin)
- * @param ticket the ticket to delete
- * @return #GNUNET_OK on success, else #GNUNET_SYSERR
- */
-static int
-identity_provider_sqlite_delete_ticket (void *cls,
-                                        const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
-{
-  struct Plugin *plugin = cls;
-  int n;
-
-  {  
-    struct GNUNET_SQ_QueryParam sparams[] = {
-      GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
-      GNUNET_SQ_query_param_uint64 (&ticket->rnd),
-      GNUNET_SQ_query_param_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_SQ_bind (plugin->delete_ticket,
-                        sparams))
-    {
-      LOG_SQLITE (plugin,
-                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
-                  "sqlite3_bind_XXXX");
-      GNUNET_SQ_reset (plugin->dbh,
-                       plugin->store_ticket);
-      return GNUNET_SYSERR;
-    }
-    n = sqlite3_step (plugin->delete_ticket);
-    GNUNET_SQ_reset (plugin->dbh,
-                     plugin->delete_ticket);
-  }
-  switch (n)
-  {
-    case SQLITE_DONE:
-      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
-                       "sqlite",
-                       "Ticket deleted\n");
-      return GNUNET_OK;
-    case SQLITE_BUSY:
-      LOG_SQLITE (plugin,
-                  GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
-                  "sqlite3_step");
-      return GNUNET_NO;
-    default:
-      LOG_SQLITE (plugin,
-                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
-                  "sqlite3_step");
-      return GNUNET_SYSERR;
-  }
-}
-
-
-/**
- * The given 'sqlite' statement has been prepared to be run.
- * It will return a record which should be given to the iterator.
- * Runs the statement and parses the returned record.
- *
- * @param plugin plugin context
- * @param stmt to run (and then clean up)
- * @param iter iterator to call with the result
- * @param iter_cls closure for @a iter
- * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
- */
-static int
-get_ticket_and_call_iterator (struct Plugin *plugin,
-                              sqlite3_stmt *stmt,
-                              GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
-                              void *iter_cls)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
-  int ret;
-  int sret;
-  size_t attrs_len;
-  char *attrs_ser;
-
-  ret = GNUNET_NO;
-  if (SQLITE_ROW == (sret = sqlite3_step (stmt)))
-  {
-    struct GNUNET_SQ_ResultSpec rs[] = {
-      GNUNET_SQ_result_spec_auto_from_type (&ticket.identity),
-      GNUNET_SQ_result_spec_auto_from_type (&ticket.audience),
-      GNUNET_SQ_result_spec_uint64 (&ticket.rnd),
-      GNUNET_SQ_result_spec_variable_size ((void**)&attrs_ser,
-                                           &attrs_len),
-      GNUNET_SQ_result_spec_end
-
-    };
-    ret = GNUNET_SQ_extract_result (stmt,
-                                    rs);
-    if (GNUNET_OK != ret)
-    {
-      GNUNET_break (0);
-      ret = GNUNET_SYSERR;
-    }
-    else
-    {
-      attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (attrs_ser,
-                                          attrs_len);
-      if (NULL != iter)
-        iter (iter_cls,
-              &ticket,
-              attrs);
-      GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs);
-      ret = GNUNET_YES;
-    }
-    GNUNET_SQ_cleanup_result (rs);
-  }
-  else
-  {
-    if (SQLITE_DONE != sret)
-      LOG_SQLITE (plugin,
-                  GNUNET_ERROR_TYPE_ERROR,
-                  "sqlite_step");
-  }
-  GNUNET_SQ_reset (plugin->dbh,
-                   stmt);
-  return ret;
-}
-
-
-/**
- * Lookup tickets in the datastore.
- *
- * @param cls closure (internal context for the plugin)
- * @param ticket the ticket to retrieve attributes for
- * @param iter function to call with the result
- * @param iter_cls closure for @a iter
- * @return #GNUNET_OK on success, else #GNUNET_SYSERR
- */
-static int
-identity_provider_sqlite_ticket_get_attrs (void *cls,
-                                           const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                                           GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
-                                           void *iter_cls)
-{
-  struct Plugin *plugin = cls;
-  struct GNUNET_SQ_QueryParam params[] = {
-    GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
-    GNUNET_SQ_query_param_uint64 (&ticket->rnd),
-    GNUNET_SQ_query_param_end
-  };
-
-  if (GNUNET_OK !=
-      GNUNET_SQ_bind (plugin->get_ticket_attrs,
-                      params))
-  {
-    LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
-                "sqlite3_bind_XXXX");
-    GNUNET_SQ_reset (plugin->dbh,
-                     plugin->get_ticket_attrs);
-    return GNUNET_SYSERR;
-  }
-  return get_ticket_and_call_iterator (plugin,
-                                       plugin->get_ticket_attrs,
-                                       iter,
-                                       iter_cls);
-}
-
-
-/**
- * Iterate over the results for a particular key and zone in the
- * datastore.  Will return at most one result to the iterator.
- *
- * @param cls closure (internal context for the plugin)
- * @param identity the issuing identity or audience (depending on audience switch)
- * @param audience GNUNET_YES if identity is audience
- * @param offset offset in the list of all matching records
- * @param iter function to call with the result
- * @param iter_cls closure for @a iter
- * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
- */
-static int
-identity_provider_sqlite_iterate_tickets (void *cls,
-                                          const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-                                          int audience,
-                                          uint64_t offset,
-                                          GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
-                                          void *iter_cls)
-{
-  struct Plugin *plugin = cls;
-  sqlite3_stmt *stmt;
-  int err;
-
-  if (NULL == identity)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  struct GNUNET_SQ_QueryParam params[] = {
-    GNUNET_SQ_query_param_auto_from_type (identity),
-    GNUNET_SQ_query_param_uint64 (&offset),
-    GNUNET_SQ_query_param_end
-  };
-  if (GNUNET_YES == audience)
-  {
-    stmt = plugin->iterate_tickets_by_audience;
-    err = GNUNET_SQ_bind (stmt,
-                          params);
-  }
-  else
-  {
-    stmt = plugin->iterate_tickets;
-    err = GNUNET_SQ_bind (stmt,
-                          params);
-  }
-  if (GNUNET_OK != err)
-  {
-    LOG_SQLITE (plugin,
-                GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
-                "sqlite3_bind_XXXX");
-    GNUNET_SQ_reset (plugin->dbh,
-                     stmt);
-    return GNUNET_SYSERR;
-  }
-  return get_ticket_and_call_iterator (plugin,
-                                       stmt,
-                                       iter,
-                                       iter_cls);
-}
-
-
-/**
- * Entry point for the plugin.
- *
- * @param cls the "struct GNUNET_IDENTITY_PROVIDER_PluginEnvironment*"
- * @return NULL on error, otherwise the plugin context
- */
-void *
-libgnunet_plugin_identity_provider_sqlite_init (void *cls)
-{
-  static struct Plugin plugin;
-  const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
-  struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *api;
-
-  if (NULL != plugin.cfg)
-    return NULL;                /* can only initialize once! */
-  memset (&plugin, 0, sizeof (struct Plugin));
-  plugin.cfg = cfg;
-  if (GNUNET_OK != database_setup (&plugin))
-  {
-    database_shutdown (&plugin);
-    return NULL;
-  }
-  api = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_PluginFunctions);
-  api->cls = &plugin;
-  api->store_ticket = &identity_provider_sqlite_store_ticket;
-  api->delete_ticket = &identity_provider_sqlite_delete_ticket;
-  api->iterate_tickets = &identity_provider_sqlite_iterate_tickets;
-  api->get_ticket_attributes = &identity_provider_sqlite_ticket_get_attrs;
-  LOG (GNUNET_ERROR_TYPE_INFO,
-       _("Sqlite database running\n"));
-  return api;
-}
-
-
-/**
- * Exit point from the plugin.
- *
- * @param cls the plugin context (as returned by "init")
- * @return always NULL
- */
-void *
-libgnunet_plugin_identity_provider_sqlite_done (void *cls)
-{
-  struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *api = cls;
-  struct Plugin *plugin = api->cls;
-
-  database_shutdown (plugin);
-  plugin->cfg = NULL;
-  GNUNET_free (api);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "sqlite plugin is finished\n");
-  return NULL;
-}
-
-/* end of plugin_identity_provider_sqlite.c */
diff --git a/src/identity-provider/plugin_rest_identity_provider.c b/src/identity-provider/plugin_rest_identity_provider.c
deleted file mode 100644 (file)
index f8176a1..0000000
+++ /dev/null
@@ -1,1253 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 GNUnet e.V.
-
-   GNUnet is free software: you can redistribute it and/or modify it
-   under the terms of the GNU Affero General Public License as published
-   by the Free Software Foundation, either version 3 of the License,
-   or (at your option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Affero General Public License for more details.
-  
-   You should have received a copy of the GNU Affero General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-   */
-/**
- * @author Martin Schanzenbach
- * @author Philippe Buschmann
- * @file identity/plugin_rest_identity.c
- * @brief GNUnet Namestore REST plugin
- *
- */
-
-#include "platform.h"
-#include "gnunet_rest_plugin.h"
-#include "gnunet_identity_service.h"
-#include "gnunet_gns_service.h"
-#include "gnunet_gnsrecord_lib.h"
-#include "gnunet_namestore_service.h"
-#include "gnunet_rest_lib.h"
-#include "gnunet_jsonapi_lib.h"
-#include "gnunet_jsonapi_util.h"
-#include "microhttpd.h"
-#include <jansson.h>
-#include <inttypes.h>
-#include "gnunet_signatures.h"
-#include "gnunet_identity_attribute_lib.h"
-#include "gnunet_identity_provider_service.h"
-
-/**
- * REST root namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp"
-
-/**
- * Attribute namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES "/idp/attributes"
-
-/**
- * Ticket namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/idp/tickets"
-
-/**
- * Revoke namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/idp/revoke"
-
-/**
- * Revoke namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume"
-
-/**
- * Attribute key
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE "attribute"
-
-/**
- * Ticket key
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket"
-
-
-/**
- * Value key
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE_VALUE "value"
-
-/**
- * State while collecting all egos
- */
-#define ID_REST_STATE_INIT 0
-
-/**
- * Done collecting egos
- */
-#define ID_REST_STATE_POST_INIT 1
-
-/**
- * The configuration handle
- */
-const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * HTTP methods allows for this plugin
- */
-static char* allow_methods;
-
-/**
- * @brief struct returned by the initialization function of the plugin
- */
-struct Plugin
-{
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-};
-
-/**
- * The ego list
- */
-struct EgoEntry
-{
-  /**
-   * DLL
-   */
-  struct EgoEntry *next;
-
-  /**
-   * DLL
-   */
-  struct EgoEntry *prev;
-
-  /**
-   * Ego Identifier
-   */
-  char *identifier;
-
-  /**
-   * Public key string
-   */
-  char *keystring;
-
-  /**
-   * The Ego
-   */
-  struct GNUNET_IDENTITY_Ego *ego;
-};
-
-
-struct RequestHandle
-{
-  /**
-   * Ego list
-   */
-  struct EgoEntry *ego_head;
-
-  /**
-   * Ego list
-   */
-  struct EgoEntry *ego_tail;
-
-  /**
-   * Selected ego
-   */
-  struct EgoEntry *ego_entry;
-
-  /**
-   * Pointer to ego private key
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
-
-  /**
-   * The processing state
-   */
-  int state;
-
-  /**
-   * Handle to Identity service.
-   */
-  struct GNUNET_IDENTITY_Handle *identity_handle;
-
-  /**
-   * Rest connection
-   */
-  struct GNUNET_REST_RequestHandle *rest_handle;
-
-  /**
-   * Handle to NAMESTORE
-   */
-  struct GNUNET_NAMESTORE_Handle *namestore_handle;
-
-  /**
-   * Iterator for NAMESTORE
-   */
-  struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it;
-
-  /**
-   * Attribute claim list
-   */
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attr_list;
-
-  /**
-   * IDENTITY Operation
-   */
-  struct GNUNET_IDENTITY_Operation *op;
-
-  /**
-   * Identity Provider
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Handle *idp;
-
-  /**
-   * Idp Operation
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
-
-  /**
-   * Attribute iterator
-   */
-  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_it;
-
-  /**
-   * Ticket iterator
-   */
-  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it;
-
-  /**
-   * A ticket
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
-
-  /**
-   * Desired timeout for the lookup (default is no timeout).
-   */
-  struct GNUNET_TIME_Relative timeout;
-
-  /**
-   * ID of a task associated with the resolution process.
-   */
-  struct GNUNET_SCHEDULER_Task *timeout_task;
-
-  /**
-   * The plugin result processor
-   */
-  GNUNET_REST_ResultProcessor proc;
-
-  /**
-   * The closure of the result processor
-   */
-  void *proc_cls;
-
-  /**
-   * The url
-   */
-  char *url;
-
-  /**
-   * Error response message
-   */
-  char *emsg;
-
-  /**
-   * Reponse code
-   */
-  int response_code;
-
-  /**
-   * Response object
-   */
-  struct GNUNET_JSONAPI_Document *resp_object;
-
-};
-
-/**
- * Cleanup lookup handle
- * @param handle Handle to clean up
- */
-static void
-cleanup_handle (struct RequestHandle *handle)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *claim_entry;
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *claim_tmp;
-  struct EgoEntry *ego_entry;
-  struct EgoEntry *ego_tmp;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Cleaning up\n");
-  if (NULL != handle->resp_object)
-    GNUNET_JSONAPI_document_delete (handle->resp_object);
-  if (NULL != handle->timeout_task)
-    GNUNET_SCHEDULER_cancel (handle->timeout_task);
-  if (NULL != handle->identity_handle)
-    GNUNET_IDENTITY_disconnect (handle->identity_handle);
-  if (NULL != handle->attr_it)
-    GNUNET_IDENTITY_PROVIDER_get_attributes_stop (handle->attr_it);
-  if (NULL != handle->ticket_it)
-    GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (handle->ticket_it);
-  if (NULL != handle->idp)
-    GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp);
-  if (NULL != handle->url)
-    GNUNET_free (handle->url);
-  if (NULL != handle->emsg)
-    GNUNET_free (handle->emsg);
-  if (NULL != handle->namestore_handle)
-    GNUNET_NAMESTORE_disconnect (handle->namestore_handle);
-  if ( NULL != handle->attr_list )
-  {
-    for (claim_entry = handle->attr_list->list_head;
-    NULL != claim_entry;)
-    {
-      claim_tmp = claim_entry;
-      claim_entry = claim_entry->next;
-      GNUNET_free(claim_tmp->claim);
-      GNUNET_free(claim_tmp);
-    }
-    GNUNET_free (handle->attr_list);
-  }
-  for (ego_entry = handle->ego_head;
-       NULL != ego_entry;)
-  {
-    ego_tmp = ego_entry;
-    ego_entry = ego_entry->next;
-    GNUNET_free (ego_tmp->identifier);
-    GNUNET_free (ego_tmp->keystring);
-    GNUNET_free (ego_tmp);
-  }
-  if (NULL != handle->attr_it)
-  {
-    GNUNET_free(handle->attr_it);
-  }
-  GNUNET_free (handle);
-}
-
-static void
-cleanup_handle_delayed (void *cls)
-{
-  cleanup_handle (cls);
-}
-
-
-/**
- * Task run on error, sends error message.  Cleans up everything.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  char *json_error;
-
-  GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\" }",
-                  handle->emsg);
-  if ( 0 == handle->response_code )
-  {
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-  }
-  resp = GNUNET_REST_create_response (json_error);
-  MHD_add_response_header (resp, "Content-Type", "application/json");
-  handle->proc (handle->proc_cls, resp, handle->response_code);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-  GNUNET_free (json_error);
-}
-
-
-/**
- * Task run on timeout, sends error message.  Cleans up everything.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_timeout (void *cls)
-{
-  struct RequestHandle *handle = cls;
-
-  handle->timeout_task = NULL;
-  do_error (handle);
-}
-
-
-static void
-collect_error_cb (void *cls)
-{
-  struct RequestHandle *handle = cls;
-
-  do_error (handle);
-}
-
-static void
-finished_cont (void *cls,
-               int32_t success,
-               const char *emsg)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-
-  resp = GNUNET_REST_create_response (emsg);
-  if (GNUNET_OK != success)
-  {
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-}
-
-
-/**
- * Return attributes for identity
- *
- * @param cls the request handle
- */
-static void
-return_response (void *cls)
-{
-  char* result_str;
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-
-  GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
-  resp = GNUNET_REST_create_response (result_str);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_free (result_str);
-  cleanup_handle (handle);
-}
-
-static void
-collect_finished_cb (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  //Done
-  handle->attr_it = NULL;
-  handle->ticket_it = NULL;
-  GNUNET_SCHEDULER_add_now (&return_response, handle);
-}
-
-
-/**
- * Collect all attributes for an ego
- *
- */
-static void
-ticket_collect (void *cls,
-                const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
-{
-  struct GNUNET_JSONAPI_Resource *json_resource;
-  struct RequestHandle *handle = cls;
-  json_t *value;
-  char* tmp;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
-  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
-                                             sizeof (uint64_t));
-  json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TICKET,
-                                                       tmp);
-  GNUNET_free (tmp);
-  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
-
-  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->identity,
-                                             sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  value = json_string (tmp);
-  GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                    "issuer",
-                                    value);
-  GNUNET_free (tmp);
-  json_decref (value);
-  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
-                                             sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  value = json_string (tmp);
-  GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                    "audience",
-                                    value);
-  GNUNET_free (tmp);
-  json_decref (value);
-  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
-                                             sizeof (uint64_t));
-  value = json_string (tmp);
-  GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                    "rnd",
-                                    value);
-  GNUNET_free (tmp);
-  json_decref (value);
-  GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (handle->ticket_it);
-}
-
-
-
-/**
- * List tickets for identity request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
-                   const char* url,
-                   void *cls)
-{
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  char *identity;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting tickets for %s.\n",
-              handle->url);
-  if ( strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >=
-       strlen (handle->url))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
-
-  for (ego_entry = handle->ego_head;
-       NULL != ego_entry;
-       ego_entry = ego_entry->next)
-    if (0 == strcmp (identity, ego_entry->identifier))
-      break;
-  handle->resp_object = GNUNET_JSONAPI_document_new ();
-
-  if (NULL == ego_entry)
-  {
-    //Done
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
-                identity);
-    GNUNET_SCHEDULER_add_now (&return_response, handle);
-    return;
-  }
-  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
-  handle->ticket_it = GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (handle->idp,
-                                                                       priv_key,
-                                                                       &collect_error_cb,
-                                                                       handle,
-                                                                       &ticket_collect,
-                                                                       handle,
-                                                                       &collect_finished_cb,
-                                                                       handle);
-}
-
-
-static void
-add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
-                    const char* url,
-                    void *cls)
-{
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
-  const char* identity;
-  const char* name_str;
-  const char* value_str;
-  const char* exp_str;
-
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct MHD_Response *resp;
-  struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attribute;
-  struct GNUNET_JSONAPI_Document *json_obj;
-  struct GNUNET_JSONAPI_Resource *json_res;
-  struct GNUNET_TIME_Relative exp;
-  char term_data[handle->rest_handle->data_size+1];
-  json_t *value_json;
-  json_t *data_json;
-  json_t *exp_json;
-  json_error_t err;
-  struct GNUNET_JSON_Specification docspec[] = {
-    GNUNET_JSON_spec_jsonapi_document (&json_obj),
-    GNUNET_JSON_spec_end()
-  };
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding an attribute for %s.\n",
-              handle->url);
-  if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >=
-       strlen (handle->url))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1;
-
-  for (ego_entry = handle->ego_head;
-       NULL != ego_entry;
-       ego_entry = ego_entry->next)
-    if (0 == strcmp (identity, ego_entry->identifier))
-      break;
-
-  if (NULL == ego_entry)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Identity unknown (%s)\n", identity);
-    GNUNET_JSONAPI_document_delete (json_obj);
-    return;
-  }
-  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-
-  if (0 >= handle->rest_handle->data_size)
-  {
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  term_data[handle->rest_handle->data_size] = '\0';
-  GNUNET_memcpy (term_data,
-                 handle->rest_handle->data,
-                 handle->rest_handle->data_size);
-  data_json = json_loads (term_data,
-                          JSON_DECODE_ANY,
-                          &err);
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_JSON_parse (data_json, docspec,
-                                    NULL, NULL));
-  json_decref (data_json);
-  if (NULL == json_obj)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unable to parse JSONAPI Object from %s\n",
-                term_data);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Cannot create more than 1 resource! (Got %d)\n",
-                GNUNET_JSONAPI_document_resource_count (json_obj));
-    GNUNET_JSONAPI_document_delete (json_obj);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
-  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
-                                                       GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unsupported JSON data type\n");
-    GNUNET_JSONAPI_document_delete (json_obj);
-    resp = GNUNET_REST_create_response (NULL);
-    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
-    cleanup_handle (handle);
-    return;
-  }
-  name_str = GNUNET_JSONAPI_resource_get_id (json_res);
-  exp_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                "exp");
-  exp_str = json_string_value (exp_json);
-  if (NULL == exp_str) {
-    exp = GNUNET_TIME_UNIT_HOURS;
-  } else {
-    if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (exp_str,
-                                           &exp)) {
-      exp = GNUNET_TIME_UNIT_HOURS;
-    }
-  }
-
-  value_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                  "value");
-  value_str = json_string_value (value_json);
-  attribute = GNUNET_IDENTITY_ATTRIBUTE_claim_new (name_str,
-                                                      GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING,
-                                                      value_str,
-                                                      strlen (value_str) + 1);
-  handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
-  handle->idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (handle->idp,
-                                                             identity_priv,
-                                                             attribute,
-                                                             &exp,
-                                                             &finished_cont,
-                                                             handle);
-  GNUNET_free (attribute);
-  GNUNET_JSONAPI_document_delete (json_obj);
-}
-
-
-
-/**
- * Collect all attributes for an ego
- *
- */
-static void
-attr_collect (void *cls,
-              const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-              const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
-{
-  struct GNUNET_JSONAPI_Resource *json_resource;
-  struct RequestHandle *handle = cls;
-  json_t *value;
-  char* tmp_value;
-  
-  if ((NULL == attr->name) || (NULL == attr->data))
-  {
-    GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
-              attr->name);
-  json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE,
-                                               attr->name);
-  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
-
-  tmp_value = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type,
-                                           attr->data,
-                                           attr->data_size);
-
-  value = json_string (tmp_value);
-
-  GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                    "value",
-                                    value);
-  json_decref (value);
-  GNUNET_free(tmp_value);
-  GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
-}
-
-
-
-/**
- * List attributes for identity request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
-                     const char* url,
-                     void *cls)
-{
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  char *identity;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting attributes for %s.\n",
-              handle->url);
-  if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >=
-       strlen (handle->url))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1;
-
-  for (ego_entry = handle->ego_head;
-       NULL != ego_entry;
-       ego_entry = ego_entry->next)
-    if (0 == strcmp (identity, ego_entry->identifier))
-      break;
-  handle->resp_object = GNUNET_JSONAPI_document_new ();
-
-
-  if (NULL == ego_entry)
-  {
-    //Done
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
-                identity);
-    GNUNET_SCHEDULER_add_now (&return_response, handle);
-    return;
-  }
-  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
-  handle->attr_it = GNUNET_IDENTITY_PROVIDER_get_attributes_start (handle->idp,
-                                                                   priv_key,
-                                                                   &collect_error_cb,
-                                                                   handle,
-                                                                   &attr_collect,
-                                                                   handle,
-                                                                   &collect_finished_cb,
-                                                                   handle);
-}
-
-
-static void
-revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
-                    const char* url,
-                    void *cls)
-{
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
-  const char* identity_str;
-  const char* audience_str;
-  const char* rnd_str;
-
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct MHD_Response *resp;
-  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
-  struct GNUNET_JSONAPI_Document *json_obj;
-  struct GNUNET_JSONAPI_Resource *json_res;
-  struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
-  char term_data[handle->rest_handle->data_size+1];
-  json_t *rnd_json;
-  json_t *identity_json;
-  json_t *audience_json;
-  json_t *data_json;
-  json_error_t err;
-  struct GNUNET_JSON_Specification docspec[] = {
-    GNUNET_JSON_spec_jsonapi_document (&json_obj),
-    GNUNET_JSON_spec_end()
-  };
-
-  if (0 >= handle->rest_handle->data_size)
-  {
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  term_data[handle->rest_handle->data_size] = '\0';
-  GNUNET_memcpy (term_data,
-                 handle->rest_handle->data,
-                 handle->rest_handle->data_size);
-  data_json = json_loads (term_data,
-                          JSON_DECODE_ANY,
-                          &err);
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_JSON_parse (data_json, docspec,
-                                    NULL, NULL));
-  json_decref (data_json);
-  if (NULL == json_obj)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unable to parse JSONAPI Object from %s\n",
-                term_data);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Cannot create more than 1 resource! (Got %d)\n",
-                GNUNET_JSONAPI_document_resource_count (json_obj));
-    GNUNET_JSONAPI_document_delete (json_obj);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
-  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
-                                                       GNUNET_REST_JSONAPI_IDENTITY_TICKET))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unsupported JSON data type\n");
-    GNUNET_JSONAPI_document_delete (json_obj);
-    resp = GNUNET_REST_create_response (NULL);
-    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
-    cleanup_handle (handle);
-    return;
-  }
-  rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                "rnd");
-  identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                     "issuer");
-  audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                     "audience");
-  rnd_str = json_string_value (rnd_json);
-  identity_str = json_string_value (identity_json);
-  audience_str = json_string_value (audience_json);
-
-  GNUNET_STRINGS_string_to_data (rnd_str,
-                                 strlen (rnd_str),
-                                 &ticket.rnd,
-                                 sizeof (uint64_t));
-  GNUNET_STRINGS_string_to_data (identity_str,
-                                 strlen (identity_str),
-                                 &ticket.identity,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  GNUNET_STRINGS_string_to_data (audience_str,
-                                 strlen (audience_str),
-                                 &ticket.audience,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
-  for (ego_entry = handle->ego_head;
-       NULL != ego_entry;
-       ego_entry = ego_entry->next)
-  {
-    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
-                                        &tmp_pk);
-    if (0 == memcmp (&ticket.identity,
-                     &tmp_pk,
-                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
-      break;
-  }
-  if (NULL == ego_entry)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Identity unknown (%s)\n", identity_str);
-    GNUNET_JSONAPI_document_delete (json_obj);
-    return;
-  }
-  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-
-  handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
-  handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (handle->idp,
-                                                           identity_priv,
-                                                           &ticket,
-                                                           &finished_cont,
-                                                           handle);
-  GNUNET_JSONAPI_document_delete (json_obj);
-}
-
-static void
-consume_cont (void *cls,
-              const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-              const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_JSONAPI_Resource *json_resource;
-  json_t *value;
-
-  if (NULL == identity)
-  {
-    GNUNET_SCHEDULER_add_now (&return_response, handle);
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
-              attr->name);
-  json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE,
-                                               attr->name);
-  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
-
-  value = json_string (attr->data);
-  GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                    "value",
-                                    value);
-  json_decref (value);
-}
-
-static void
-consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
-                     const char* url,
-                     void *cls)
-{
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
-  const char* identity_str;
-  const char* audience_str;
-  const char* rnd_str;
-
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct MHD_Response *resp;
-  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
-  struct GNUNET_JSONAPI_Document *json_obj;
-  struct GNUNET_JSONAPI_Resource *json_res;
-  struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
-  char term_data[handle->rest_handle->data_size+1];
-  json_t *rnd_json;
-  json_t *identity_json;
-  json_t *audience_json;
-  json_t *data_json;
-  json_error_t err;
-  struct GNUNET_JSON_Specification docspec[] = {
-    GNUNET_JSON_spec_jsonapi_document (&json_obj),
-    GNUNET_JSON_spec_end()
-  };
-
-  if (0 >= handle->rest_handle->data_size)
-  {
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  term_data[handle->rest_handle->data_size] = '\0';
-  GNUNET_memcpy (term_data,
-                 handle->rest_handle->data,
-                 handle->rest_handle->data_size);
-  data_json = json_loads (term_data,
-                          JSON_DECODE_ANY,
-                          &err);
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_JSON_parse (data_json, docspec,
-                                    NULL, NULL));
-  json_decref (data_json);
-  if (NULL == json_obj)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unable to parse JSONAPI Object from %s\n",
-                term_data);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Cannot create more than 1 resource! (Got %d)\n",
-                GNUNET_JSONAPI_document_resource_count (json_obj));
-    GNUNET_JSONAPI_document_delete (json_obj);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
-  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
-                                                       GNUNET_REST_JSONAPI_IDENTITY_TICKET))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unsupported JSON data type\n");
-    GNUNET_JSONAPI_document_delete (json_obj);
-    resp = GNUNET_REST_create_response (NULL);
-    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
-    cleanup_handle (handle);
-    return;
-  }
-  rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                "rnd");
-  identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                     "identity");
-  audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                     "audience");
-  rnd_str = json_string_value (rnd_json);
-  identity_str = json_string_value (identity_json);
-  audience_str = json_string_value (audience_json);
-
-  GNUNET_STRINGS_string_to_data (rnd_str,
-                                 strlen (rnd_str),
-                                 &ticket.rnd,
-                                 sizeof (uint64_t));
-  GNUNET_STRINGS_string_to_data (identity_str,
-                                 strlen (identity_str),
-                                 &ticket.identity,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  GNUNET_STRINGS_string_to_data (audience_str,
-                                 strlen (audience_str),
-                                 &ticket.audience,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
-  for (ego_entry = handle->ego_head;
-       NULL != ego_entry;
-       ego_entry = ego_entry->next)
-  {
-    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
-                                        &tmp_pk);
-    if (0 == memcmp (&ticket.audience,
-                     &tmp_pk,
-                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
-      break;
-  }
-  if (NULL == ego_entry)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Identity unknown (%s)\n", identity_str);
-    GNUNET_JSONAPI_document_delete (json_obj);
-    return;
-  }
-  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  handle->resp_object = GNUNET_JSONAPI_document_new ();
-  handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
-  handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (handle->idp,
-                                                            identity_priv,
-                                                            &ticket,
-                                                            &consume_cont,
-                                                            handle);
-  GNUNET_JSONAPI_document_delete (json_obj);
-}
-
-
-
-/**
- * Respond to OPTIONS request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-options_cont (struct GNUNET_REST_RequestHandle *con_handle,
-              const char* url,
-              void *cls)
-{
-  struct MHD_Response *resp;
-  struct RequestHandle *handle = cls;
-
-  //For now, independent of path return all options
-  resp = GNUNET_REST_create_response (NULL);
-  MHD_add_response_header (resp,
-                           "Access-Control-Allow-Methods",
-                           allow_methods);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  cleanup_handle (handle);
-  return;
-}
-
-/**
- * Handle rest request
- *
- * @param handle the request handle
- */
-static void
-init_cont (struct RequestHandle *handle)
-{
-  struct GNUNET_REST_RequestHandlerError err;
-  static const struct GNUNET_REST_RequestHandler handlers[] = {
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &list_attribute_cont},
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &add_attribute_cont},
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont},
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont},
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont},
-    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER,
-      &options_cont},
-    GNUNET_REST_HANDLER_END
-  };
-
-  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
-                                               handlers,
-                                               &err,
-                                               handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-/**
- * If listing is enabled, prints information about the egos.
- *
- * This function is initially called for all egos and then again
- * whenever a ego's identifier changes or if it is deleted.  At the
- * end of the initial pass over all egos, the function is once called
- * with 'NULL' for 'ego'. That does NOT mean that the callback won't
- * be invoked in the future or that there was an error.
- *
- * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
- * this function is only called ONCE, and 'NULL' being passed in
- * 'ego' does indicate an error (i.e. name is taken or no default
- * value is known).  If 'ego' is non-NULL and if '*ctx'
- * is set in those callbacks, the value WILL be passed to a subsequent
- * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
- * that one was not NULL).
- *
- * When an identity is renamed, this function is called with the
- * (known) ego but the NEW identifier.
- *
- * When an identity is deleted, this function is called with the
- * (known) ego and "NULL" for the 'identifier'.  In this case,
- * the 'ego' is henceforth invalid (and the 'ctx' should also be
- * cleaned up).
- *
- * @param cls closure
- * @param ego ego handle
- * @param ctx context for application to store data for this ego
- *                 (during the lifetime of this process, initially NULL)
- * @param identifier identifier 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
-list_ego (void *cls,
-          struct GNUNET_IDENTITY_Ego *ego,
-          void **ctx,
-          const char *identifier)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
-
-  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
-  {
-    handle->state = ID_REST_STATE_POST_INIT;
-    init_cont (handle);
-    return;
-  }
-  if (ID_REST_STATE_INIT == handle->state) {
-    ego_entry = GNUNET_new (struct EgoEntry);
-    GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
-    ego_entry->keystring =
-      GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
-    ego_entry->ego = ego;
-    ego_entry->identifier = GNUNET_strdup (identifier);
-    GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
-  }
-
-}
-
-static void
-rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
-                              GNUNET_REST_ResultProcessor proc,
-                              void *proc_cls)
-{
-  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
-  handle->response_code = 0;
-  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
-  handle->proc_cls = proc_cls;
-  handle->proc = proc;
-  handle->state = ID_REST_STATE_INIT;
-  handle->rest_handle = rest_handle;
-
-  handle->url = GNUNET_strdup (rest_handle->url);
-  if (handle->url[strlen (handle->url)-1] == '/')
-    handle->url[strlen (handle->url)-1] = '\0';
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connecting...\n");
-  handle->identity_handle = GNUNET_IDENTITY_connect (cfg,
-                                                     &list_ego,
-                                                     handle);
-  handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg);
-  handle->timeout_task =
-    GNUNET_SCHEDULER_add_delayed (handle->timeout,
-                                  &do_timeout,
-                                  handle);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connected\n");
-}
-
-/**
- * Entry point for the plugin.
- *
- * @param cls Config info
- * @return NULL on error, otherwise the plugin context
- */
-void *
-libgnunet_plugin_rest_identity_provider_init (void *cls)
-{
-  static struct Plugin plugin;
-  struct GNUNET_REST_Plugin *api;
-
-  cfg = cls;
-  if (NULL != plugin.cfg)
-    return NULL;                /* can only initialize once! */
-  memset (&plugin, 0, sizeof (struct Plugin));
-  plugin.cfg = cfg;
-  api = GNUNET_new (struct GNUNET_REST_Plugin);
-  api->cls = &plugin;
-  api->name = GNUNET_REST_API_NS_IDENTITY_PROVIDER;
-  api->process_request = &rest_identity_process_request;
-  GNUNET_asprintf (&allow_methods,
-                   "%s, %s, %s, %s, %s",
-                   MHD_HTTP_METHOD_GET,
-                   MHD_HTTP_METHOD_POST,
-                   MHD_HTTP_METHOD_PUT,
-                   MHD_HTTP_METHOD_DELETE,
-                   MHD_HTTP_METHOD_OPTIONS);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              _("Identity Provider REST API initialized\n"));
-  return api;
-}
-
-
-/**
- * Exit point from the plugin.
- *
- * @param cls the plugin context (as returned by "init")
- * @return always NULL
- */
-void *
-libgnunet_plugin_rest_identity_provider_done (void *cls)
-{
-  struct GNUNET_REST_Plugin *api = cls;
-  struct Plugin *plugin = api->cls;
-  plugin->cfg = NULL;
-
-  GNUNET_free_non_null (allow_methods);
-  GNUNET_free (api);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Identity Provider REST plugin is finished\n");
-  return NULL;
-}
-
-/* end of plugin_rest_identity_provider.c */
diff --git a/src/identity-provider/plugin_rest_openid_connect.c b/src/identity-provider/plugin_rest_openid_connect.c
deleted file mode 100644 (file)
index cc4b83d..0000000
+++ /dev/null
@@ -1,2227 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 GNUnet e.V.
-
-   GNUnet is free software: you can redistribute it and/or modify it
-   under the terms of the GNU Affero General Public License as published
-   by the Free Software Foundation, either version 3 of the License,
-   or (at your option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Affero General Public License for more details.
-  
-   You should have received a copy of the GNU Affero General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-   */
-/**
- * @author Martin Schanzenbach
- * @author Philippe Buschmann
- * @file identity/plugin_rest_openid_connect.c
- * @brief GNUnet Namestore REST plugin
- *
- */
-
-#include "platform.h"
-#include "gnunet_rest_plugin.h"
-#include "gnunet_identity_service.h"
-#include "gnunet_gns_service.h"
-#include "gnunet_gnsrecord_lib.h"
-#include "gnunet_namestore_service.h"
-#include "gnunet_rest_lib.h"
-#include "gnunet_jsonapi_lib.h"
-#include "gnunet_jsonapi_util.h"
-#include "microhttpd.h"
-#include <jansson.h>
-#include <inttypes.h>
-#include "gnunet_signatures.h"
-#include "gnunet_identity_attribute_lib.h"
-#include "gnunet_identity_provider_service.h"
-#include "jwt.h"
-
-/**
- * REST root namespace
- */
-#define GNUNET_REST_API_NS_OIDC "/openid"
-
-/**
- * Authorize endpoint
- */
-#define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize"
-
-/**
- * Token endpoint
- */
-#define GNUNET_REST_API_NS_TOKEN "/openid/token"
-
-/**
- * UserInfo endpoint
- */
-#define GNUNET_REST_API_NS_USERINFO "/openid/userinfo"
-
-/**
- * Login namespace
- */
-#define GNUNET_REST_API_NS_LOGIN "/openid/login"
-
-/**
- * Attribute key
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE "attribute"
-
-/**
- * Ticket key
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket"
-
-
-/**
- * Value key
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE_VALUE "value"
-
-/**
- * State while collecting all egos
- */
-#define ID_REST_STATE_INIT 0
-
-/**
- * Done collecting egos
- */
-#define ID_REST_STATE_POST_INIT 1
-
-/**
- * OIDC grant_type key
- */
-#define OIDC_GRANT_TYPE_KEY "grant_type"
-
-/**
- * OIDC grant_type key
- */
-#define OIDC_GRANT_TYPE_VALUE "authorization_code"
-
-/**
- * OIDC code key
- */
-#define OIDC_CODE_KEY "code"
-
-/**
- * OIDC response_type key
- */
-#define OIDC_RESPONSE_TYPE_KEY "response_type"
-
-/**
- * OIDC client_id key
- */
-#define OIDC_CLIENT_ID_KEY "client_id"
-
-/**
- * OIDC scope key
- */
-#define OIDC_SCOPE_KEY "scope"
-
-/**
- * OIDC redirect_uri key
- */
-#define OIDC_REDIRECT_URI_KEY "redirect_uri"
-
-/**
- * OIDC state key
- */
-#define OIDC_STATE_KEY "state"
-
-/**
- * OIDC nonce key
- */
-#define OIDC_NONCE_KEY "nonce"
-
-/**
- * OIDC cookie header key
- */
-#define OIDC_COOKIE_HEADER_KEY "cookie"
-
-/**
- * OIDC cookie header information key
- */
-#define OIDC_AUTHORIZATION_HEADER_KEY "authorization"
-
-/**
- * OIDC cookie header information key
- */
-#define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity="
-
-/**
- * OIDC expected response_type while authorizing
- */
-#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code"
-
-/**
- * OIDC expected scope part while authorizing
- */
-#define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid"
-
-/**
- * OIDC ignored parameter array
- */
-static char* OIDC_ignored_parameter_array [] =
-{
-  "display",
-  "prompt",
-  "max_age",
-  "ui_locales", 
-  "response_mode",
-  "id_token_hint",
-  "login_hint", 
-  "acr_values"
-};
-
-/**
- * OIDC authorized identities and times hashmap
- */
-struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_login_time;
-
-/**
- * OIDC authorized identities and times hashmap
- */
-struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_grants;
-
-/**
- * OIDC ticket/code use only once
- */
-struct GNUNET_CONTAINER_MultiHashMap *OIDC_ticket_once;
-
-/**
- * OIDC access_token to ticket and ego
- */
-struct GNUNET_CONTAINER_MultiHashMap *OIDC_interpret_access_token;
-
-/**
- * The configuration handle
- */
-const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * HTTP methods allows for this plugin
- */
-static char* allow_methods;
-
-/**
- * @brief struct returned by the initialization function of the plugin
- */
-struct Plugin
-{
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-};
-
-/**
- * OIDC needed variables
- */
-struct OIDC_Variables
-{
-  /**
-   * The RP client public key
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey client_pkey;
-
-  /**
-   * The OIDC client id of the RP
-   */
-  char *client_id;
-
-  /**
-   * GNUNET_YES if there is a delegation to 
-   * this RP or if it is a local identity
-   */
-  int is_client_trusted;
-
-  /**
-   * The OIDC redirect uri
-   */
-  char *redirect_uri;
-
-  /**
-   * The list of oidc scopes
-   */
-  char *scope;
-
-  /**
-   * The OIDC state
-   */
-  char *state;
-
-  /**
-   * The OIDC nonce
-   */
-  char *nonce;
-
-  /**
-   * The OIDC response type
-   */
-  char *response_type;
-
-  /**
-   * The identity chosen by the user to login
-   */
-  char *login_identity;
-
-  /**
-   * The response JSON
-   */
-  json_t *response;
-
-};
-
-/**
- * The ego list
- */
-struct EgoEntry
-{
-  /**
-   * DLL
-   */
-  struct EgoEntry *next;
-
-  /**
-   * DLL
-   */
-  struct EgoEntry *prev;
-
-  /**
-   * Ego Identifier
-   */
-  char *identifier;
-
-  /**
-   * Public key string
-   */
-  char *keystring;
-
-  /**
-   * The Ego
-   */
-  struct GNUNET_IDENTITY_Ego *ego;
-};
-
-
-struct RequestHandle
-{
-  /**
-   * Ego list
-   */
-  struct EgoEntry *ego_head;
-
-  /**
-   * Ego list
-   */
-  struct EgoEntry *ego_tail;
-
-  /**
-   * Selected ego
-   */
-  struct EgoEntry *ego_entry;
-
-  /**
-   * Pointer to ego private key
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
-
-  /**
-   * OIDC variables
-   */
-  struct OIDC_Variables *oidc;
-
-  /**
-   * The processing state
-   */
-  int state;
-
-  /**
-   * Handle to Identity service.
-   */
-  struct GNUNET_IDENTITY_Handle *identity_handle;
-
-  /**
-   * Rest connection
-   */
-  struct GNUNET_REST_RequestHandle *rest_handle;
-
-  /**
-   * Handle to NAMESTORE
-   */
-  struct GNUNET_NAMESTORE_Handle *namestore_handle;
-
-  /**
-   * Iterator for NAMESTORE
-   */
-  struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it;
-
-  /**
-   * Attribute claim list
-   */
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attr_list;
-
-  /**
-   * IDENTITY Operation
-   */
-  struct GNUNET_IDENTITY_Operation *op;
-
-  /**
-   * Identity Provider
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Handle *idp;
-
-  /**
-   * Idp Operation
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
-
-  /**
-   * Attribute iterator
-   */
-  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_it;
-
-  /**
-   * Ticket iterator
-   */
-  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it;
-
-  /**
-   * A ticket
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
-
-  /**
-   * Desired timeout for the lookup (default is no timeout).
-   */
-  struct GNUNET_TIME_Relative timeout;
-
-  /**
-   * ID of a task associated with the resolution process.
-   */
-  struct GNUNET_SCHEDULER_Task *timeout_task;
-
-  /**
-   * The plugin result processor
-   */
-  GNUNET_REST_ResultProcessor proc;
-
-  /**
-   * The closure of the result processor
-   */
-  void *proc_cls;
-
-  /**
-   * The url
-   */
-  char *url;
-
-  /**
-   * The tld for redirect
-   */
-  char *tld;
-
-  /**
-   * Error response message
-   */
-  char *emsg;
-
-  /**
-   * Error response description
-   */
-  char *edesc;
-
-  /**
-   * Reponse code
-   */
-  int response_code;
-
-  /**
-   * Response object
-   */
-  struct GNUNET_JSONAPI_Document *resp_object;
-
-};
-
-/**
- * Cleanup lookup handle
- * @param handle Handle to clean up
- */
-static void
-cleanup_handle (struct RequestHandle *handle)
-{
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *claim_entry;
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *claim_tmp;
-  struct EgoEntry *ego_entry;
-  struct EgoEntry *ego_tmp;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Cleaning up\n");
-  if (NULL != handle->resp_object)
-    GNUNET_JSONAPI_document_delete (handle->resp_object);
-  if (NULL != handle->timeout_task)
-    GNUNET_SCHEDULER_cancel (handle->timeout_task);
-  if (NULL != handle->identity_handle)
-    GNUNET_IDENTITY_disconnect (handle->identity_handle);
-  if (NULL != handle->attr_it)
-    GNUNET_IDENTITY_PROVIDER_get_attributes_stop (handle->attr_it);
-  if (NULL != handle->ticket_it)
-    GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (handle->ticket_it);
-  if (NULL != handle->idp)
-    GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp);
-  if (NULL != handle->url)
-    GNUNET_free (handle->url);
-  if (NULL != handle->tld)
-    GNUNET_free (handle->tld);
-  if (NULL != handle->emsg)
-    GNUNET_free (handle->emsg);
-  if (NULL != handle->edesc)
-    GNUNET_free (handle->edesc);
-  if (NULL != handle->namestore_handle)
-    GNUNET_NAMESTORE_disconnect (handle->namestore_handle);
-  if (NULL != handle->oidc)
-  {
-    if (NULL != handle->oidc->client_id)
-      GNUNET_free(handle->oidc->client_id);
-    if (NULL != handle->oidc->login_identity)
-      GNUNET_free(handle->oidc->login_identity);
-    if (NULL != handle->oidc->nonce)
-      GNUNET_free(handle->oidc->nonce);
-    if (NULL != handle->oidc->redirect_uri)
-      GNUNET_free(handle->oidc->redirect_uri);
-    if (NULL != handle->oidc->response_type)
-      GNUNET_free(handle->oidc->response_type);
-    if (NULL != handle->oidc->scope)
-      GNUNET_free(handle->oidc->scope);
-    if (NULL != handle->oidc->state)
-      GNUNET_free(handle->oidc->state);
-    if (NULL != handle->oidc->response)
-      json_decref(handle->oidc->response);
-    GNUNET_free(handle->oidc);
-  }
-  if ( NULL != handle->attr_list )
-  {
-    for (claim_entry = handle->attr_list->list_head;
-         NULL != claim_entry;)
-    {
-      claim_tmp = claim_entry;
-      claim_entry = claim_entry->next;
-      GNUNET_free(claim_tmp->claim);
-      GNUNET_free(claim_tmp);
-    }
-    GNUNET_free (handle->attr_list);
-  }
-  for (ego_entry = handle->ego_head;
-       NULL != ego_entry;)
-  {
-    ego_tmp = ego_entry;
-    ego_entry = ego_entry->next;
-    GNUNET_free (ego_tmp->identifier);
-    GNUNET_free (ego_tmp->keystring);
-    GNUNET_free (ego_tmp);
-  }
-  if (NULL != handle->attr_it)
-  {
-    GNUNET_free(handle->attr_it);
-  }
-  GNUNET_free (handle);
-}
-
-static void
-cleanup_handle_delayed (void *cls)
-{
-  cleanup_handle (cls);
-}
-
-
-/**
- * Task run on error, sends error message.  Cleans up everything.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  char *json_error;
-
-  GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
-                   handle->emsg,
-                   (NULL != handle->edesc) ? handle->edesc : "",
-                   (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
-                   (NULL != handle->oidc->state) ? handle->oidc->state : "",
-                   (NULL != handle->oidc->state) ? "\"" : "");
-  if ( 0 == handle->response_code )
-  {
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-  }
-  resp = GNUNET_REST_create_response (json_error);
-  if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
-  {
-    MHD_add_response_header(resp, "WWW-Authenticate", "Basic");
-  }
-  MHD_add_response_header (resp, "Content-Type", "application/json");
-  handle->proc (handle->proc_cls, resp, handle->response_code);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-  GNUNET_free (json_error);
-}
-
-
-/**
- * Task run on error in userinfo endpoint, sends error header. Cleans up
- * everything
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_userinfo_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  char *error;
-
-  GNUNET_asprintf (&error, "error=\"%s\", error_description=\"%s\"",
-                   handle->emsg,
-                   (NULL != handle->edesc) ? handle->edesc : "");
-  resp = GNUNET_REST_create_response ("");
-  MHD_add_response_header(resp, "WWW-Authenticate", error);
-  handle->proc (handle->proc_cls, resp, handle->response_code);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-  GNUNET_free (error);
-}
-
-
-/**
- * Task run on error, sends error message and redirects. Cleans up everything.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_redirect_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  char* redirect;
-  GNUNET_asprintf (&redirect,
-                   "%s?error=%s&error_description=%s%s%s",
-                   handle->oidc->redirect_uri, handle->emsg, handle->edesc,
-                   (NULL != handle->oidc->state) ? "&state=" : "",
-                   (NULL != handle->oidc->state) ? handle->oidc->state : "");
-  resp = GNUNET_REST_create_response ("");
-  MHD_add_response_header (resp, "Location", redirect);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-  GNUNET_free (redirect);
-}
-
-/**
- * Task run on timeout, sends error message.  Cleans up everything.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_timeout (void *cls)
-{
-  struct RequestHandle *handle = cls;
-
-  handle->timeout_task = NULL;
-  do_error (handle);
-}
-
-/**
- * Return attributes for claim
- *
- * @param cls the request handle
- */
-static void
-return_userinfo_response (void *cls)
-{
-  char* result_str;
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-
-  result_str = json_dumps (handle->oidc->response, 0);
-
-  resp = GNUNET_REST_create_response (result_str);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_free (result_str);
-  cleanup_handle (handle);
-}
-
-/**
- * Returns base64 encoded string without padding
- *
- * @param string the string to encode
- * @return base64 encoded string
- */
-static char*
-base_64_encode(const char *s)
-{
-  char *enc;
-  char *tmp;
-
-  GNUNET_STRINGS_base64_encode(s, strlen(s), &enc);
-  tmp = strrchr (enc, '=');
-  *tmp = '\0';
-  return enc;
-}
-
-/**
- * Respond to OPTIONS request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-options_cont (struct GNUNET_REST_RequestHandle *con_handle,
-              const char* url,
-              void *cls)
-{
-  struct MHD_Response *resp;
-  struct RequestHandle *handle = cls;
-
-  //For now, independent of path return all options
-  resp = GNUNET_REST_create_response (NULL);
-  MHD_add_response_header (resp,
-                           "Access-Control-Allow-Methods",
-                           allow_methods);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  cleanup_handle (handle);
-  return;
-}
-
-/**
- * Interprets cookie header and pass its identity keystring to handle
- */
-static void
-cookie_identity_interpretation (struct RequestHandle *handle)
-{
-  struct GNUNET_HashCode cache_key;
-  char *cookies;
-  struct GNUNET_TIME_Absolute current_time, *relog_time;
-  char delimiter[] = "; ";
-
-  //gets identity of login try with cookie
-  GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY, strlen (OIDC_COOKIE_HEADER_KEY),
-                      &cache_key);
-  if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map,
-                                                             &cache_key) )
-  {
-    //splits cookies and find 'Identity' cookie
-    cookies = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key);
-    handle->oidc->login_identity = strtok(cookies, delimiter);
-
-    while ( NULL != handle->oidc->login_identity )
-    {
-      if ( NULL != strstr (handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY) )
-      {
-        break;
-      }
-      handle->oidc->login_identity = strtok (NULL, delimiter);
-    }
-    GNUNET_CRYPTO_hash (handle->oidc->login_identity, strlen (handle->oidc->login_identity),
-                        &cache_key);
-    if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time, &cache_key) )
-    {
-      relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time,
-                                                      &cache_key);
-      current_time = GNUNET_TIME_absolute_get ();
-      // 30 min after old login -> redirect to login
-      if ( current_time.abs_value_us <= relog_time->abs_value_us )
-      {
-        handle->oidc->login_identity = strtok(handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY);
-        handle->oidc->login_identity = GNUNET_strdup(handle->oidc->login_identity);
-      } else {
-        handle->oidc->login_identity = NULL;
-      }
-    }
-    else
-    {
-      handle->oidc->login_identity = NULL;
-    }
-  }
-}
-
-/**
- * Redirects to login page stored in configuration file
- */
-static void
-login_redirection(void *cls)
-{
-  char *login_base_url;
-  char *new_redirect;
-  struct MHD_Response *resp;
-  struct RequestHandle *handle = cls;
-
-  if ( GNUNET_OK
-       == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin",
-                                                 "address", &login_base_url) )
-  {
-    GNUNET_asprintf (&new_redirect, "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s",
-                     login_base_url,
-                     OIDC_RESPONSE_TYPE_KEY,
-                     handle->oidc->response_type,
-                     OIDC_CLIENT_ID_KEY,
-                     handle->oidc->client_id,
-                     OIDC_REDIRECT_URI_KEY,
-                     handle->oidc->redirect_uri,
-                     OIDC_SCOPE_KEY,
-                     handle->oidc->scope,
-                     OIDC_STATE_KEY,
-                     (NULL != handle->oidc->state) ? handle->oidc->state : "",
-                     OIDC_NONCE_KEY,
-                     (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "");
-    resp = GNUNET_REST_create_response ("");
-    MHD_add_response_header (resp, "Location", new_redirect);
-    GNUNET_free(login_base_url);
-  }
-  else
-  {
-    handle->emsg = GNUNET_strdup("server_error");
-    handle->edesc = GNUNET_strdup ("gnunet configuration failed");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
-  GNUNET_free(new_redirect);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-}
-
-/**
- * Does internal server error when iteration failed.
- */
-static void
-oidc_iteration_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  handle->emsg = GNUNET_strdup("INTERNAL_SERVER_ERROR");
-  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-  GNUNET_SCHEDULER_add_now (&do_error, handle);
-}
-
-static void get_client_name_result (void *cls,
-                                    const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                                    const char *label,
-                                    unsigned int rd_count,
-                                    const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  char *ticket_str;
-  char *redirect_uri;
-  char *code_json_string;
-  char *code_base64_final_string;
-  char *redirect_path;
-  char *tmp;
-  char *tmp_prefix;
-  char *prefix;
-  ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket,
-                                                    sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
-  //TODO change if more attributes are needed (see max_age)
-  GNUNET_asprintf (&code_json_string, "{\"ticket\":\"%s\"%s%s%s}",
-                   ticket_str,
-                   (NULL != handle->oidc->nonce) ? ", \"nonce\":\"" : "",
-                   (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "",
-                   (NULL != handle->oidc->nonce) ? "\"" : "");
-  code_base64_final_string = base_64_encode(code_json_string);
-  tmp = GNUNET_strdup (handle->oidc->redirect_uri);
-  redirect_path = strtok (tmp, "/");
-  redirect_path = strtok (NULL, "/");
-  redirect_path = strtok (NULL, "/");
-  tmp_prefix = GNUNET_strdup (handle->oidc->redirect_uri);
-  prefix = strrchr (tmp_prefix,
-                    (unsigned char) '.');
-  *prefix = '\0';
-  GNUNET_asprintf (&redirect_uri, "%s.%s/%s?%s=%s&state=%s",
-                   tmp_prefix,
-                   handle->tld,
-                   redirect_path,
-                   handle->oidc->response_type,
-                   code_base64_final_string, handle->oidc->state);
-  resp = GNUNET_REST_create_response ("");
-  MHD_add_response_header (resp, "Location", redirect_uri);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-  GNUNET_free (tmp);
-  GNUNET_free (tmp_prefix);
-  GNUNET_free (redirect_uri);
-  GNUNET_free (ticket_str);
-  GNUNET_free (code_json_string);
-  GNUNET_free (code_base64_final_string);
-  return;
-}
-
-static void
-get_client_name_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-
-  handle->emsg = GNUNET_strdup("server_error");
-  handle->edesc = GNUNET_strdup("Server cannot generate ticket, no name found for client.");
-  GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-}
-
-/**
- * Issues ticket and redirects to relying party with the authorization code as
- * parameter. Otherwise redirects with error
- */
-static void
-oidc_ticket_issue_cb (void* cls,
-                      const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
-{
-  struct RequestHandle *handle = cls;
-  handle->idp_op = NULL;
-  handle->ticket = *ticket;
-  if (NULL != ticket) {
-    GNUNET_NAMESTORE_zone_to_name (handle->namestore_handle,
-                                   &handle->priv_key,
-                                   &handle->oidc->client_pkey,
-                                   &get_client_name_error,
-                                   handle,
-                                   &get_client_name_result,
-                                   handle);
-    return;
-  }
-  handle->emsg = GNUNET_strdup("server_error");
-  handle->edesc = GNUNET_strdup("Server cannot generate ticket.");
-  GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-}
-
-static void
-oidc_collect_finished_cb (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  handle->attr_it = NULL;
-  handle->ticket_it = NULL;
-  if (NULL == handle->attr_list->list_head)
-  {
-    handle->emsg = GNUNET_strdup("invalid_scope");
-    handle->edesc = GNUNET_strdup("The requested scope is not available.");
-    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-    return;
-  }
-  handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_issue (handle->idp,
-                                                          &handle->priv_key,
-                                                          &handle->oidc->client_pkey,
-                                                          handle->attr_list,
-                                                          &oidc_ticket_issue_cb,
-                                                          handle);
-}
-
-
-/**
- * Collects all attributes for an ego if in scope parameter
- */
-static void
-oidc_attr_collect (void *cls,
-                   const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-                   const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-  char* scope_variables;
-  char* scope_variable;
-  char delimiter[]=" ";
-
-  if ( (NULL == attr->name) || (NULL == attr->data) )
-  {
-    GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
-    return;
-  }
-
-  scope_variables = GNUNET_strdup(handle->oidc->scope);
-  scope_variable = strtok (scope_variables, delimiter);
-  while (NULL != scope_variable)
-  {
-    if ( 0 == strcmp (attr->name, scope_variable) )
-    {
-      break;
-    }
-    scope_variable = strtok (NULL, delimiter);
-  }
-  if ( NULL == scope_variable )
-  {
-    GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
-    GNUNET_free(scope_variables);
-    return;
-  }
-  GNUNET_free(scope_variables);
-
-  le = GNUNET_new(struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
-  le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr->name, attr->type,
-                                                   attr->data, attr->data_size);
-  GNUNET_CONTAINER_DLL_insert(handle->attr_list->list_head,
-                              handle->attr_list->list_tail, le);
-  GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
-}
-
-
-/**
- * Checks time and cookie and redirects accordingly
- */
-static void
-login_check (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_TIME_Absolute current_time, *relog_time;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pubkey, ego_pkey;
-  struct GNUNET_HashCode cache_key;
-  char *identity_cookie;
-
-  GNUNET_asprintf (&identity_cookie, "Identity=%s", handle->oidc->login_identity);
-  GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
-  GNUNET_free(identity_cookie);
-  //No login time for identity -> redirect to login
-  if ( GNUNET_YES
-       == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time,
-                                                  &cache_key) )
-  {
-    relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time,
-                                                    &cache_key);
-    current_time = GNUNET_TIME_absolute_get ();
-    // 30 min after old login -> redirect to login
-    if ( current_time.abs_value_us <= relog_time->abs_value_us )
-    {
-      if ( GNUNET_OK
-           != GNUNET_CRYPTO_ecdsa_public_key_from_string (
-                                                          handle->oidc->login_identity,
-                                                          strlen (handle->oidc->login_identity), &pubkey) )
-      {
-        handle->emsg = GNUNET_strdup("invalid_cookie");
-        handle->edesc = GNUNET_strdup(
-                                      "The cookie of a login identity is not valid");
-        GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-        return;
-      }
-      // iterate over egos and compare their public key
-      for (handle->ego_entry = handle->ego_head;
-           NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next)
-      {
-        GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
-        if ( 0
-             == memcmp (&ego_pkey, &pubkey,
-                        sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
-        {
-          handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (
-                                                                   handle->ego_entry->ego);
-          handle->resp_object = GNUNET_JSONAPI_document_new ();
-          handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
-          handle->attr_list = GNUNET_new(
-                                         struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
-          handle->attr_it = GNUNET_IDENTITY_PROVIDER_get_attributes_start (
-                                                                           handle->idp, &handle->priv_key, &oidc_iteration_error, handle,
-                                                                           &oidc_attr_collect, handle, &oidc_collect_finished_cb, handle);
-          return;
-        }
-      }
-      //handle->emsg = GNUNET_strdup("invalid_cookie");
-      //handle->edesc = GNUNET_strdup(
-      //                              "The cookie of the login identity is not valid");
-      //GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-      GNUNET_SCHEDULER_add_now (&login_redirection,handle);
-      return;
-    }
-  }
-}
-
-/**
- * Searches for client_id in namestore. If found trust status stored in handle
- * Else continues to search
- *
- * @param handle the RequestHandle
- */
-static void
-namestore_iteration_callback (
-                              void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
-                              const char *rname, unsigned int rd_len,
-                              const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_CRYPTO_EcdsaPublicKey login_identity_pkey;
-  struct GNUNET_CRYPTO_EcdsaPublicKey current_zone_pkey;
-  int i;
-
-  for (i = 0; i < rd_len; i++)
-  {
-    if ( GNUNET_GNSRECORD_TYPE_PKEY != rd[i].record_type )
-      continue;
-
-    if ( NULL != handle->oidc->login_identity )
-    {
-      GNUNET_CRYPTO_ecdsa_public_key_from_string (
-                                                  handle->oidc->login_identity,
-                                                  strlen (handle->oidc->login_identity),
-                                                  &login_identity_pkey);
-      GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego,
-                                          &current_zone_pkey);
-
-      if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey,
-                        sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
-      {
-        if ( 0 == memcmp (&login_identity_pkey, &current_zone_pkey,
-                          sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
-        {
-          handle->oidc->is_client_trusted = GNUNET_YES;
-        }
-      }
-    }
-    else
-    {
-      if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey,
-                        sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
-      {
-        handle->oidc->is_client_trusted = GNUNET_YES;
-      }
-    }
-  }
-
-  GNUNET_NAMESTORE_zone_iterator_next (handle->namestore_handle_it,
-                                      1);
-}
-
-
-/**
- * Iteration over all results finished, build final
- * response.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-namestore_iteration_finished (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_HashCode cache_key;
-
-  char *expected_scope;
-  char delimiter[]=" ";
-  int number_of_ignored_parameter, iterator;
-
-
-  handle->ego_entry = handle->ego_entry->next;
-
-  if(NULL != handle->ego_entry)
-  {
-    handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego);
-    handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start (handle->namestore_handle, &handle->priv_key,
-                                                                         &oidc_iteration_error, handle, &namestore_iteration_callback, handle,
-                                                                         &namestore_iteration_finished, handle);
-    return;
-  }
-  if (GNUNET_NO == handle->oidc->is_client_trusted)
-  {
-    handle->emsg = GNUNET_strdup("unauthorized_client");
-    handle->edesc = GNUNET_strdup("The client is not authorized to request an "
-                                  "authorization code using this method.");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  // REQUIRED value: redirect_uri
-  GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY),
-                      &cache_key);
-  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                                           &cache_key))
-  {
-    handle->emsg=GNUNET_strdup("invalid_request");
-    handle->edesc=GNUNET_strdup("missing parameter redirect_uri");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->oidc->redirect_uri = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
-                                                                                &cache_key));
-
-  // REQUIRED value: response_type
-  GNUNET_CRYPTO_hash (OIDC_RESPONSE_TYPE_KEY, strlen (OIDC_RESPONSE_TYPE_KEY),
-                      &cache_key);
-  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                                           &cache_key))
-  {
-    handle->emsg=GNUNET_strdup("invalid_request");
-    handle->edesc=GNUNET_strdup("missing parameter response_type");
-    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-    return;
-  }
-  handle->oidc->response_type = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
-                                                                  &cache_key);
-  handle->oidc->response_type = GNUNET_strdup (handle->oidc->response_type);
-
-  // REQUIRED value: scope
-  GNUNET_CRYPTO_hash (OIDC_SCOPE_KEY, strlen (OIDC_SCOPE_KEY), &cache_key);
-  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                                           &cache_key))
-  {
-    handle->emsg=GNUNET_strdup("invalid_request");
-    handle->edesc=GNUNET_strdup("missing parameter scope");
-    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-    return;
-  }
-  handle->oidc->scope = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
-                                                          &cache_key);
-  handle->oidc->scope = GNUNET_strdup(handle->oidc->scope);
-
-  //OPTIONAL value: nonce
-  GNUNET_CRYPTO_hash (OIDC_NONCE_KEY, strlen (OIDC_NONCE_KEY), &cache_key);
-  if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                                            &cache_key))
-  {
-    handle->oidc->nonce = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
-                                                            &cache_key);
-    handle->oidc->nonce = GNUNET_strdup (handle->oidc->nonce);
-  }
-
-  //TODO check other values if needed
-  number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
-  for( iterator = 0; iterator < number_of_ignored_parameter; iterator++ )
-  {
-    GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator],
-                        strlen(OIDC_ignored_parameter_array[iterator]),
-                        &cache_key);
-    if(GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(handle->rest_handle->url_param_map,
-                                                            &cache_key))
-    {
-      handle->emsg=GNUNET_strdup("access_denied");
-      GNUNET_asprintf (&handle->edesc, "Server will not handle parameter: %s",
-                       OIDC_ignored_parameter_array[iterator]);
-      GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-      return;
-    }
-  }
-
-  // Checks if response_type is 'code'
-  if( 0 != strcmp( handle->oidc->response_type, OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE ) )
-  {
-    handle->emsg=GNUNET_strdup("unsupported_response_type");
-    handle->edesc=GNUNET_strdup("The authorization server does not support "
-                                "obtaining this authorization code.");
-    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-    return;
-  }
-
-  // Checks if scope contains 'openid'
-  expected_scope = GNUNET_strdup(handle->oidc->scope);
-  char* test;
-  test = strtok (expected_scope, delimiter);
-  while (NULL != test)
-  {
-    if ( 0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope) )
-    {
-      break;
-    }
-    test = strtok (NULL, delimiter);
-  }
-  if (NULL == test)
-  {
-    handle->emsg = GNUNET_strdup("invalid_scope");
-    handle->edesc=GNUNET_strdup("The requested scope is invalid, unknown, or "
-                                "malformed.");
-    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-    GNUNET_free(expected_scope);
-    return;
-  }
-
-  GNUNET_free(expected_scope);
-
-  if( NULL != handle->oidc->login_identity )
-  {
-    GNUNET_SCHEDULER_add_now(&login_check,handle);
-    return;
-  }
-
-  GNUNET_SCHEDULER_add_now(&login_redirection,handle);
-}
-
-/**
- * Responds to authorization GET and url-encoded POST request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
-                    const char* url,
-                    void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_HashCode cache_key;
-  struct EgoEntry *tmp_ego;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-
-  cookie_identity_interpretation(handle);
-
-  //RECOMMENDED value: state - REQUIRED for answers
-  GNUNET_CRYPTO_hash (OIDC_STATE_KEY, strlen (OIDC_STATE_KEY), &cache_key);
-  if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                                            &cache_key))
-  {
-    handle->oidc->state = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
-                                                            &cache_key);
-    handle->oidc->state = GNUNET_strdup (handle->oidc->state);
-  }
-
-  // REQUIRED value: client_id
-  GNUNET_CRYPTO_hash (OIDC_CLIENT_ID_KEY, strlen (OIDC_CLIENT_ID_KEY),
-                      &cache_key);
-  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                                           &cache_key))
-  {
-    handle->emsg=GNUNET_strdup("invalid_request");
-    handle->edesc=GNUNET_strdup("missing parameter client_id");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->oidc->client_id = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
-                                                                             &cache_key));
-
-  if ( GNUNET_OK
-       != GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->oidc->client_id,
-                                                      strlen (handle->oidc->client_id),
-                                                      &handle->oidc->client_pkey) )
-  {
-    handle->emsg = GNUNET_strdup("unauthorized_client");
-    handle->edesc = GNUNET_strdup("The client is not authorized to request an "
-                                  "authorization code using this method.");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-
-  if ( NULL == handle->ego_head )
-  {
-    handle->emsg = GNUNET_strdup("server_error");
-    handle->edesc = GNUNET_strdup ("Egos are missing");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  handle->ego_entry = handle->ego_head;
-  handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
-  handle->oidc->is_client_trusted = GNUNET_NO;
-
-  //First check if client_id is one of our egos; TODO: handle other TLD cases: Delegation, from config
-  for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
-  {
-    priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
-    GNUNET_CRYPTO_ecdsa_key_get_public (priv_key,
-                                        &pkey);
-    if ( 0 == memcmp (&pkey, &handle->oidc->client_pkey,
-                      sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
-    {
-      handle->tld = GNUNET_strdup (tmp_ego->identifier);
-      handle->oidc->is_client_trusted = GNUNET_YES;
-      handle->ego_entry = handle->ego_tail;
-    }
-  }
-
-
-  // Checks if client_id is valid:
-  handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start (
-                                                                       handle->namestore_handle, &handle->priv_key, &oidc_iteration_error,
-                                                                       handle, &namestore_iteration_callback, handle,
-                                                                       &namestore_iteration_finished, handle);
-}
-
-/**
- * Combines an identity with a login time and responds OK to login request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-login_cont (struct GNUNET_REST_RequestHandle *con_handle,
-            const char* url,
-            void *cls)
-{
-  struct MHD_Response *resp = GNUNET_REST_create_response ("");
-  struct RequestHandle *handle = cls;
-  struct GNUNET_HashCode cache_key;
-  struct GNUNET_TIME_Absolute *current_time;
-  struct GNUNET_TIME_Absolute *last_time;
-  char* cookie;
-  json_t *root;
-  json_error_t error;
-  json_t *identity;
-  char term_data[handle->rest_handle->data_size+1];
-  term_data[handle->rest_handle->data_size] = '\0';
-  GNUNET_memcpy (term_data, handle->rest_handle->data, handle->rest_handle->data_size);
-  root = json_loads (term_data, JSON_DECODE_ANY, &error);
-  identity = json_object_get (root, "identity");
-  if ( json_is_string(identity) )
-  {
-    GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
-    MHD_add_response_header (resp, "Set-Cookie", cookie);
-    MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST");
-    GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
-
-    current_time = GNUNET_new(struct GNUNET_TIME_Absolute);
-    *current_time = GNUNET_TIME_relative_to_absolute (
-                                                      GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (),
-                                                                                     5));
-    last_time = GNUNET_CONTAINER_multihashmap_get(OIDC_identity_login_time, &cache_key);
-    if (NULL != last_time)
-    {
-      GNUNET_free(last_time);
-    }
-    GNUNET_CONTAINER_multihashmap_put (
-                                       OIDC_identity_login_time, &cache_key, current_time,
-                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
-
-    handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-    GNUNET_free(cookie);
-  }
-  else
-  {
-    handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
-  }
-  json_decref (root);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-  return;
-}
-
-/**
- * Responds to token url-encoded POST request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
-                const char* url,
-                void *cls)
-{
-  //TODO static strings
-  struct RequestHandle *handle = cls;
-  struct GNUNET_HashCode cache_key;
-  char *authorization, *credentials;
-  char delimiter[]=" ";
-  char delimiter_user_psw[]=":";
-  char *grant_type, *code;
-  char *user_psw = NULL, *client_id, *psw;
-  char *expected_psw;
-  int client_exists = GNUNET_NO;
-  struct MHD_Response *resp;
-  char* code_output;
-  json_t *root, *ticket_string, *nonce, *max_age;
-  json_error_t error;
-  char *json_response;
-  char *jwt_secret;
-
-  /*
-   * Check Authorization
-   */
-  GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
-                      strlen (OIDC_AUTHORIZATION_HEADER_KEY),
-                      &cache_key);
-  if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map,
-                                                            &cache_key) )
-  {
-    handle->emsg=GNUNET_strdup("invalid_client");
-    handle->edesc=GNUNET_strdup("missing authorization");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  authorization = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key);
-
-  //split header in "Basic" and [content]
-  credentials = strtok (authorization, delimiter);
-  if (0 != strcmp ("Basic",credentials))
-  {
-    handle->emsg=GNUNET_strdup("invalid_client");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  credentials = strtok(NULL, delimiter);
-  if (NULL == credentials)
-  {
-    handle->emsg=GNUNET_strdup("invalid_client");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  GNUNET_STRINGS_base64_decode (credentials, strlen (credentials), (void**)&user_psw);
-
-  if ( NULL == user_psw )
-  {
-    handle->emsg=GNUNET_strdup("invalid_client");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  client_id = strtok (user_psw, delimiter_user_psw);
-  if ( NULL == client_id )
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg=GNUNET_strdup("invalid_client");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  psw = strtok (NULL, delimiter_user_psw);
-  if (NULL == psw)
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg=GNUNET_strdup("invalid_client");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  //check client password
-  if ( GNUNET_OK
-       == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin",
-                                                 "psw", &expected_psw) )
-  {
-    if (0 != strcmp (expected_psw, psw))
-    {
-      GNUNET_free_non_null(user_psw);
-      GNUNET_free(expected_psw);
-      handle->emsg=GNUNET_strdup("invalid_client");
-      handle->response_code = MHD_HTTP_UNAUTHORIZED;
-      GNUNET_SCHEDULER_add_now (&do_error, handle);
-      return;
-    }
-    GNUNET_free(expected_psw);
-  }
-  else
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg = GNUNET_strdup("server_error");
-    handle->edesc = GNUNET_strdup ("gnunet configuration failed");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  //check client_id
-  for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry->next; )
-  {
-    if ( 0 == strcmp(handle->ego_entry->keystring, client_id))
-    {
-      client_exists = GNUNET_YES;
-      break;
-    }
-    handle->ego_entry = handle->ego_entry->next;
-  }
-  if (GNUNET_NO == client_exists)
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg=GNUNET_strdup("invalid_client");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  /*
-   * Check parameter
-   */
-
-  //TODO Do not allow multiple equal parameter names
-  //REQUIRED grant_type
-  GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY, strlen (OIDC_GRANT_TYPE_KEY), &cache_key);
-  if ( GNUNET_NO
-       == GNUNET_CONTAINER_multihashmap_contains (
-                                                  handle->rest_handle->url_param_map, &cache_key) )
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("missing parameter grant_type");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  grant_type = GNUNET_CONTAINER_multihashmap_get (
-                                                  handle->rest_handle->url_param_map, &cache_key);
-
-  //REQUIRED code
-  GNUNET_CRYPTO_hash (OIDC_CODE_KEY, strlen (OIDC_CODE_KEY), &cache_key);
-  if ( GNUNET_NO
-       == GNUNET_CONTAINER_multihashmap_contains (
-                                                  handle->rest_handle->url_param_map, &cache_key) )
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("missing parameter code");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  code = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
-                                            &cache_key);
-
-  //REQUIRED redirect_uri
-  GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY),
-                      &cache_key);
-  if ( GNUNET_NO
-       == GNUNET_CONTAINER_multihashmap_contains (
-                                                  handle->rest_handle->url_param_map, &cache_key) )
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("missing parameter redirect_uri");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  //Check parameter grant_type == "authorization_code"
-  if (0 != strcmp(OIDC_GRANT_TYPE_VALUE, grant_type))
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg=GNUNET_strdup("unsupported_grant_type");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  GNUNET_CRYPTO_hash (code, strlen (code), &cache_key);
-  int i = 1;
-  if ( GNUNET_SYSERR
-       == GNUNET_CONTAINER_multihashmap_put (OIDC_ticket_once,
-                                             &cache_key,
-                                             &i,
-                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) )
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("Cannot use the same code more than once");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  //decode code
-  GNUNET_STRINGS_base64_decode(code,strlen(code), (void**)&code_output);
-  root = json_loads (code_output, 0, &error);
-  GNUNET_free(code_output);
-  ticket_string = json_object_get (root, "ticket");
-  nonce = json_object_get (root, "nonce");
-  max_age = json_object_get (root, "max_age");
-
-  if(ticket_string == NULL && !json_is_string(ticket_string))
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("invalid code");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket = GNUNET_new(struct GNUNET_IDENTITY_PROVIDER_Ticket);
-  if ( GNUNET_OK
-       != GNUNET_STRINGS_string_to_data (json_string_value(ticket_string),
-                                         strlen (json_string_value(ticket_string)),
-                                         ticket,
-                                         sizeof(struct GNUNET_IDENTITY_PROVIDER_Ticket)))
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("invalid code");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    GNUNET_free(ticket);
-    return;
-  }
-  // this is the current client (relying party)
-  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
-  GNUNET_IDENTITY_ego_get_public_key(handle->ego_entry->ego,&pub_key);
-  if (0 != memcmp(&pub_key,&ticket->audience,sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("invalid code");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    GNUNET_free(ticket);
-    return;
-  }
-
-  //create jwt
-  unsigned long long int expiration_time;
-  if ( GNUNET_OK
-       != GNUNET_CONFIGURATION_get_value_number(cfg, "identity-rest-plugin",
-                                                "expiration_time", &expiration_time) )
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg = GNUNET_strdup("server_error");
-    handle->edesc = GNUNET_strdup ("gnunet configuration failed");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    GNUNET_free(ticket);
-    return;
-  }
-
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *cl = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
-  //aud REQUIRED public key client_id must be there
-  GNUNET_IDENTITY_ATTRIBUTE_list_add(cl,
-                                     "aud",
-                                     GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING,
-                                     client_id,
-                                     strlen(client_id));
-  //exp REQUIRED time expired from config
-  struct GNUNET_TIME_Absolute exp_time = GNUNET_TIME_relative_to_absolute (
-                                                                           GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (),
-                                                                                                          expiration_time));
-  const char* exp_time_string = GNUNET_STRINGS_absolute_time_to_string(exp_time);
-  GNUNET_IDENTITY_ATTRIBUTE_list_add (cl,
-                                      "exp",
-                                      GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING,
-                                      exp_time_string,
-                                      strlen(exp_time_string));
-  //iat REQUIRED time now
-  struct GNUNET_TIME_Absolute time_now = GNUNET_TIME_absolute_get();
-  const char* time_now_string = GNUNET_STRINGS_absolute_time_to_string(time_now);
-  GNUNET_IDENTITY_ATTRIBUTE_list_add (cl,
-                                      "iat",
-                                      GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING,
-                                      time_now_string,
-                                      strlen(time_now_string));
-  //nonce only if nonce is provided
-  if ( NULL != nonce && json_is_string(nonce) )
-  {
-    GNUNET_IDENTITY_ATTRIBUTE_list_add (cl,
-                                        "nonce",
-                                        GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING,
-                                        json_string_value(nonce),
-                                        strlen(json_string_value(nonce)));
-  }
-  //auth_time only if max_age is provided
-  if ( NULL != max_age && json_is_string(max_age) )
-  {
-    GNUNET_IDENTITY_ATTRIBUTE_list_add (cl,
-                                        "auth_time",
-                                        GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING,
-                                        json_string_value(max_age),
-                                        strlen(json_string_value(max_age)));
-  }
-  //TODO OPTIONAL acr,amr,azp
-
-  struct EgoEntry *ego_entry;
-  for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next)
-  {
-    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
-    if (0 == memcmp (&pub_key, &ticket->audience, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
-    {
-      break;
-    }
-  }
-  if ( NULL == ego_entry )
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("invalid code...");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    GNUNET_free(ticket);
-    return;
-  }
-  if ( GNUNET_OK
-       != GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin",
-                                                 "jwt_secret", &jwt_secret) )
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("No signing secret configured!");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    GNUNET_free(ticket);
-    return;
-  }
-  struct GNUNET_CRYPTO_AuthKey jwt_sign_key;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
-  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pk);
-  GNUNET_CRYPTO_hash (jwt_secret, strlen (jwt_secret), (struct GNUNET_HashCode*)jwt_sign_key.key);
-  char *id_token = jwt_create_from_list(&ticket->audience,
-                                        &pk,
-                                        cl,
-                                        &jwt_sign_key);
-
-  //Create random access_token
-  char* access_token_number;
-  char* access_token;
-  uint64_t random_number;
-  random_number = GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
-  GNUNET_asprintf(&access_token_number, "%" PRIu64, random_number);
-  GNUNET_STRINGS_base64_encode(access_token_number,strlen(access_token_number),&access_token);
-
-
-
-  //TODO OPTIONAL add refresh_token and scope
-  GNUNET_asprintf (&json_response,
-                   "{ \"access_token\" : \"%s\", "
-                   "\"token_type\" : \"Bearer\", "
-                   "\"expires_in\" : %d, "
-                   "\"id_token\" : \"%s\"}",
-                   access_token,
-                   expiration_time,
-                   id_token);
-  GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key);
-  char *id_ticket_combination;
-  GNUNET_asprintf(&id_ticket_combination,
-                  "%s;%s",
-                  client_id,
-                  json_string_value(ticket_string));
-  GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token,
-                                    &cache_key,
-                                    id_ticket_combination,
-                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
-
-  resp = GNUNET_REST_create_response (json_response);
-  MHD_add_response_header (resp, "Cache-Control", "no-store");
-  MHD_add_response_header (resp, "Pragma", "no-cache");
-  MHD_add_response_header (resp, "Content-Type", "application/json");
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-
-  GNUNET_IDENTITY_ATTRIBUTE_list_destroy(cl);
-  GNUNET_free(access_token_number);
-  GNUNET_free(access_token);
-  GNUNET_free(user_psw);
-  GNUNET_free(json_response);
-  GNUNET_free(ticket);
-  GNUNET_free(id_token);
-  json_decref (root);
-  GNUNET_SCHEDULER_add_now(&cleanup_handle_delayed, handle);
-}
-
-/**
- * Collects claims and stores them in handle
- */
-static void
-consume_ticket (void *cls,
-                const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-                const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
-{
-  struct RequestHandle *handle = cls;
-  char *tmp_value;
-  json_t *value;
-
-  if (NULL == identity)
-  {
-    GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle);
-    return;
-  }
-
-  tmp_value = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type,
-                                                         attr->data,
-                                                         attr->data_size);
-
-  value = json_string (tmp_value);
-
-
-  json_object_set_new (handle->oidc->response,
-                       attr->name,
-                       value);
-  GNUNET_free (tmp_value);
-}
-
-/**
- * Responds to userinfo GET and url-encoded POST request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
-                   const char* url, void *cls)
-{
-  //TODO expiration time
-  struct RequestHandle *handle = cls;
-  char delimiter[] = " ";
-  char delimiter_db[] = ";";
-  struct GNUNET_HashCode cache_key;
-  char *authorization, *authorization_type, *authorization_access_token;
-  char *client_ticket, *client, *ticket_str;
-  struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
-
-  GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
-                      strlen (OIDC_AUTHORIZATION_HEADER_KEY),
-                      &cache_key);
-  if ( GNUNET_NO
-       == GNUNET_CONTAINER_multihashmap_contains (
-                                                  handle->rest_handle->header_param_map, &cache_key) )
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("No Access Token");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    return;
-  }
-  authorization = GNUNET_CONTAINER_multihashmap_get (
-                                                     handle->rest_handle->header_param_map, &cache_key);
-
-  //split header in "Bearer" and access_token
-  authorization = GNUNET_strdup(authorization);
-  authorization_type = strtok (authorization, delimiter);
-  if ( 0 != strcmp ("Bearer", authorization_type) )
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("No Access Token");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    GNUNET_free(authorization);
-    return;
-  }
-  authorization_access_token = strtok (NULL, delimiter);
-  if ( NULL == authorization_access_token )
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("No Access Token");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    GNUNET_free(authorization);
-    return;
-  }
-
-  GNUNET_CRYPTO_hash (authorization_access_token,
-                      strlen (authorization_access_token),
-                      &cache_key);
-  if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (OIDC_interpret_access_token,
-                                                            &cache_key) )
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("The Access Token expired");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    GNUNET_free(authorization);
-    return;
-  }
-
-  client_ticket = GNUNET_CONTAINER_multihashmap_get(OIDC_interpret_access_token,
-                                                    &cache_key);
-  client_ticket = GNUNET_strdup(client_ticket);
-  client = strtok(client_ticket,delimiter_db);
-  if (NULL == client)
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("The Access Token expired");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    GNUNET_free(authorization);
-    GNUNET_free(client_ticket);
-    return;
-  }
-  handle->ego_entry = handle->ego_head;
-  for(; NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next)
-  {
-    if (0 == strcmp(handle->ego_entry->keystring,client))
-    {
-      break;
-    }
-  }
-  if (NULL == handle->ego_entry)
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("The Access Token expired");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    GNUNET_free(authorization);
-    GNUNET_free(client_ticket);
-    return;
-  }
-  ticket_str = strtok(NULL, delimiter_db);
-  if (NULL == ticket_str)
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("The Access Token expired");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    GNUNET_free(authorization);
-    GNUNET_free(client_ticket);
-    return;
-  }
-  ticket = GNUNET_new(struct GNUNET_IDENTITY_PROVIDER_Ticket);
-  if ( GNUNET_OK
-       != GNUNET_STRINGS_string_to_data (ticket_str,
-                                         strlen (ticket_str),
-                                         ticket,
-                                         sizeof(struct GNUNET_IDENTITY_PROVIDER_Ticket)))
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("The Access Token expired");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    GNUNET_free(ticket);
-    GNUNET_free(authorization);
-    GNUNET_free(client_ticket);
-    return;
-  }
-
-  handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
-  handle->oidc->response = json_object();
-  json_object_set_new( handle->oidc->response, "sub", json_string( handle->ego_entry->keystring));
-  handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (
-                                                            handle->idp,
-                                                            GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego),
-                                                            ticket,
-                                                            consume_ticket,
-                                                            handle);
-  GNUNET_free(ticket);
-  GNUNET_free(authorization);
-  GNUNET_free(client_ticket);
-
-}
-
-
-/**
- * Handle rest request
- *
- * @param handle the request handle
- */
-static void
-init_cont (struct RequestHandle *handle)
-{
-  struct GNUNET_REST_RequestHandlerError err;
-  static const struct GNUNET_REST_RequestHandler handlers[] = {
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint},
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint}, //url-encoded
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont},
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
-    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC,
-      &options_cont},
-    GNUNET_REST_HANDLER_END
-  };
-
-  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
-                                               handlers,
-                                               &err,
-                                               handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-/**
- * If listing is enabled, prints information about the egos.
- *
- * This function is initially called for all egos and then again
- * whenever a ego's identifier changes or if it is deleted.  At the
- * end of the initial pass over all egos, the function is once called
- * with 'NULL' for 'ego'. That does NOT mean that the callback won't
- * be invoked in the future or that there was an error.
- *
- * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
- * this function is only called ONCE, and 'NULL' being passed in
- * 'ego' does indicate an error (i.e. name is taken or no default
- * value is known).  If 'ego' is non-NULL and if '*ctx'
- * is set in those callbacks, the value WILL be passed to a subsequent
- * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
- * that one was not NULL).
- *
- * When an identity is renamed, this function is called with the
- * (known) ego but the NEW identifier.
- *
- * When an identity is deleted, this function is called with the
- * (known) ego and "NULL" for the 'identifier'.  In this case,
- * the 'ego' is henceforth invalid (and the 'ctx' should also be
- * cleaned up).
- *
- * @param cls closure
- * @param ego ego handle
- * @param ctx context for application to store data for this ego
- *                 (during the lifetime of this process, initially NULL)
- * @param identifier identifier 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
-list_ego (void *cls,
-          struct GNUNET_IDENTITY_Ego *ego,
-          void **ctx,
-          const char *identifier)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
-
-  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
-  {
-    handle->state = ID_REST_STATE_POST_INIT;
-    init_cont (handle);
-    return;
-  }
-  if (ID_REST_STATE_INIT == handle->state) {
-    ego_entry = GNUNET_new (struct EgoEntry);
-    GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
-    ego_entry->keystring =
-      GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
-    ego_entry->ego = ego;
-    ego_entry->identifier = GNUNET_strdup (identifier);
-    GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
-    return;
-  }
-  /* Ego renamed or added */
-  if (identifier != NULL) {
-    for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) {
-      if (ego_entry->ego == ego) {
-        /* Rename */
-        GNUNET_free (ego_entry->identifier);
-        ego_entry->identifier = GNUNET_strdup (identifier);
-        break;
-      }
-    }
-    if (NULL == ego_entry) {
-      /* Add */
-      ego_entry = GNUNET_new (struct EgoEntry);
-      GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
-      ego_entry->keystring =
-        GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
-      ego_entry->ego = ego;
-      ego_entry->identifier = GNUNET_strdup (identifier);
-      GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
-    }
-  } else {
-    /* Delete */
-    for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) {
-      if (ego_entry->ego == ego)
-        break;
-    }
-    if (NULL != ego_entry)
-      GNUNET_CONTAINER_DLL_remove(handle->ego_head,handle->ego_tail, ego_entry);
-  }
-
-}
-
-static void
-rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
-                              GNUNET_REST_ResultProcessor proc,
-                              void *proc_cls)
-{
-  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
-  handle->oidc = GNUNET_new (struct OIDC_Variables);
-  if ( NULL == OIDC_identity_login_time )
-    OIDC_identity_login_time = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
-  if ( NULL == OIDC_identity_grants )
-    OIDC_identity_grants = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
-  if ( NULL == OIDC_ticket_once )
-    OIDC_ticket_once = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
-  if ( NULL == OIDC_interpret_access_token )
-    OIDC_interpret_access_token = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
-  handle->response_code = 0;
-  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
-  handle->proc_cls = proc_cls;
-  handle->proc = proc;
-  handle->state = ID_REST_STATE_INIT;
-  handle->rest_handle = rest_handle;
-
-  handle->url = GNUNET_strdup (rest_handle->url);
-  if (handle->url[strlen (handle->url)-1] == '/')
-    handle->url[strlen (handle->url)-1] = '\0';
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connecting...\n");
-  handle->identity_handle = GNUNET_IDENTITY_connect (cfg,
-                                                     &list_ego,
-                                                     handle);
-  handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg);
-  handle->timeout_task =
-    GNUNET_SCHEDULER_add_delayed (handle->timeout,
-                                  &do_timeout,
-                                  handle);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connected\n");
-}
-
-/**
- * Entry point for the plugin.
- *
- * @param cls Config info
- * @return NULL on error, otherwise the plugin context
- */
-void *
-libgnunet_plugin_rest_openid_connect_init (void *cls)
-{
-  static struct Plugin plugin;
-  struct GNUNET_REST_Plugin *api;
-
-  cfg = cls;
-  if (NULL != plugin.cfg)
-    return NULL;                /* can only initialize once! */
-  memset (&plugin, 0, sizeof (struct Plugin));
-  plugin.cfg = cfg;
-  api = GNUNET_new (struct GNUNET_REST_Plugin);
-  api->cls = &plugin;
-  api->name = GNUNET_REST_API_NS_OIDC;
-  api->process_request = &rest_identity_process_request;
-  GNUNET_asprintf (&allow_methods,
-                   "%s, %s, %s, %s, %s",
-                   MHD_HTTP_METHOD_GET,
-                   MHD_HTTP_METHOD_POST,
-                   MHD_HTTP_METHOD_PUT,
-                   MHD_HTTP_METHOD_DELETE,
-                   MHD_HTTP_METHOD_OPTIONS);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              _("Identity Provider REST API initialized\n"));
-  return api;
-}
-
-
-/**
- * Exit point from the plugin.
- *
- * @param cls the plugin context (as returned by "init")
- * @return always NULL
- */
-void *
-libgnunet_plugin_rest_openid_connect_done (void *cls)
-{
-  struct GNUNET_REST_Plugin *api = cls;
-  struct Plugin *plugin = api->cls;
-  plugin->cfg = NULL;
-
-  struct GNUNET_CONTAINER_MultiHashMapIterator *hashmap_it;
-  void *value = NULL;
-  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (
-                                                              OIDC_identity_login_time);
-  while (GNUNET_YES ==
-         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
-  {
-    if (NULL != value)
-      GNUNET_free(value);
-  }
-  GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_login_time);
-  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_identity_grants);
-  while (GNUNET_YES ==
-         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
-  {
-    if (NULL != value)
-      GNUNET_free(value);
-  }
-  GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_grants);
-  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_ticket_once);
-  while (GNUNET_YES ==
-         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
-  {
-    if (NULL != value)
-      GNUNET_free(value);
-  }
-  GNUNET_CONTAINER_multihashmap_destroy(OIDC_ticket_once);
-  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_interpret_access_token);
-  while (GNUNET_YES ==
-         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
-  {
-    if (NULL != value)
-      GNUNET_free(value);
-  }
-  GNUNET_CONTAINER_multihashmap_destroy(OIDC_interpret_access_token);
-  GNUNET_CONTAINER_multihashmap_iterator_destroy(hashmap_it);
-  GNUNET_free_non_null (allow_methods);
-  GNUNET_free (api);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Identity Provider REST plugin is finished\n");
-  return NULL;
-}
-
-/* end of plugin_rest_identity_provider.c */
diff --git a/src/identity-provider/test_idp.conf b/src/identity-provider/test_idp.conf
deleted file mode 100644 (file)
index 3e4df56..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-@INLINE@ test_idp_defaults.conf
-
-[PATHS]
-GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-idp-peer-1/
-
-[dht]
-START_ON_DEMAND = YES
-
-[rest]
-START_ON_DEMAND = YES
-PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=$GNUNET_TMP/restlog
-
-[transport]
-PLUGINS =
-
-[identity-provider]
-START_ON_DEMAND = YES
-#PREFIX = valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file=$GNUNET_TMP/idplog
-
-[gns]
-#PREFIX = valgrind --leak-check=full --track-origins=yes
-START_ON_DEMAND = YES
-AUTO_IMPORT_PKEY = YES
-MAX_PARALLEL_BACKGROUND_QUERIES = 10
-DEFAULT_LOOKUP_TIMEOUT = 15 s
-RECORD_PUT_INTERVAL = 1 h
-ZONE_PUBLISH_TIME_WINDOW = 1 h
-DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
-
-[identity-rest-plugin]
-address = http://localhost:8000/#/login
-psw = mysupersecretpassword
-expiration_time = 3600
diff --git a/src/identity-provider/test_idp.sh b/src/identity-provider/test_idp.sh
deleted file mode 100755 (executable)
index 598d100..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-#trap "gnunet-arm -e -c test_idp_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_idp.conf -s PATHS -o GNUNET_HOME -f`
-
-#  (1) PKEY1.user -> PKEY2.resu.user
-#  (2) PKEY2.resu -> PKEY3
-#  (3) PKEY3.user -> PKEY4
-
-
-which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
-
-TEST_ATTR="test"
-gnunet-arm -s -c test_idp.conf
-gnunet-identity -C testego -c test_idp.conf
-valgrind gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf
-gnunet-idp -e testego -a name -V John -c test_idp.conf
-gnunet-idp -e testego -D -c test_idp.conf
-gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_attribute.sh b/src/identity-provider/test_idp_attribute.sh
deleted file mode 100755 (executable)
index 7f0f06d..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-trap "gnunet-arm -e -c test_idp.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_idp.conf -s PATHS -o GNUNET_HOME -f`
-
-#  (1) PKEY1.user -> PKEY2.resu.user
-#  (2) PKEY2.resu -> PKEY3
-#  (3) PKEY3.user -> PKEY4
-
-
-which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
-
-TEST_ATTR="test"
-gnunet-arm -s -c test_idp.conf
-#gnunet-arm -i rest -c test_idp.conf
-gnunet-identity -C testego -c test_idp.conf
-gnunet-identity -C rpego -c test_idp.conf
-TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}')
-gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf
-gnunet-idp -e testego -a name -V John -c test_idp.conf > /dev/null 2>&1
-if test $? != 0
-then
-  echo "Failed."
-  exit 1
-fi
-
-#curl localhost:7776/idp/attributes/testego
-gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_consume.sh b/src/identity-provider/test_idp_consume.sh
deleted file mode 100755 (executable)
index 11f6865..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-trap "gnunet-arm -e -c test_idp.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_idp.conf -s PATHS -o GNUNET_HOME -f`
-
-#  (1) PKEY1.user -> PKEY2.resu.user
-#  (2) PKEY2.resu -> PKEY3
-#  (3) PKEY3.user -> PKEY4
-
-
-which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
-
-TEST_ATTR="test"
-gnunet-arm -s -c test_idp.conf
-#gnunet-arm -i rest -c test_idp.conf
-gnunet-identity -C testego -c test_idp.conf
-gnunet-identity -C rpego -c test_idp.conf
-SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print $3}')
-TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}')
-gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf
-gnunet-idp -e testego -a name -V John -c test_idp.conf
-TICKET=$(gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf | awk '{print $1}')
-gnunet-idp -e rpego -C $TICKET -c test_idp.conf > /dev/null 2>&1
-
-if test $? != 0
-then
-  "Failed."
-  exit 1
-fi
-#curl http://localhost:7776/idp/tickets/testego
-gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_defaults.conf b/src/identity-provider/test_idp_defaults.conf
deleted file mode 100644 (file)
index a9a197d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
-
-[PATHS]
-GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-idp-testing/
-
-[namestore-sqlite]
-FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
-
-[namecache-sqlite]
-FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db
-
-[identity]
-# Directory where we store information about our egos
-EGODIR = $GNUNET_TEST_HOME/identity/egos/
-
-[dhtcache]
-DATABASE = heap
-
-[transport]
-PLUGINS = tcp
-
-[transport-tcp]
-BINDTO = 127.0.0.1
-
diff --git a/src/identity-provider/test_idp_issue.sh b/src/identity-provider/test_idp_issue.sh
deleted file mode 100755 (executable)
index 90487ee..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/bash
-trap "gnunet-arm -e -c test_idp.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_idp.conf -s PATHS -o GNUNET_HOME -f`
-
-#  (1) PKEY1.user -> PKEY2.resu.user
-#  (2) PKEY2.resu -> PKEY3
-#  (3) PKEY3.user -> PKEY4
-
-
-which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
-
-TEST_ATTR="test"
-gnunet-arm -s -c test_idp.conf
-#gnunet-arm -i rest -c test_idp.conf
-gnunet-identity -C testego -c test_idp.conf
-gnunet-identity -C rpego -c test_idp.conf
-SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print $3}')
-TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}')
-gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf > /dev/null 2>&1
-gnunet-idp -e testego -a name -V John -c test_idp.conf > /dev/null 2>&1
-#gnunet-idp -e testego -D -c test_idp.conf
-gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf > /dev/null 2>&1
-if test $? != 0
-then
-  echo "Failed."
-  exit 1
-fi
-#curl http://localhost:7776/idp/attributes/testego
-gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_revoke.sh b/src/identity-provider/test_idp_revoke.sh
deleted file mode 100755 (executable)
index 7a3f5d0..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/bin/bash
-trap "gnunet-arm -e -c test_idp.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_idp.conf -s PATHS -o GNUNET_HOME -f`
-
-#  (1) PKEY1.user -> PKEY2.resu.user
-#  (2) PKEY2.resu -> PKEY3
-#  (3) PKEY3.user -> PKEY4
-
-
-which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
-
-TEST_ATTR="test"
-gnunet-arm -s -c test_idp.conf 2&>1 > /dev/null
-gnunet-identity -C alice -c test_idp.conf
-gnunet-identity -C bob -c test_idp.conf
-gnunet-identity -C eve -c test_idp.conf
-ALICE_KEY=$(gnunet-identity -d -c test_idp.conf | grep alice | awk '{print $3}')
-BOB_KEY=$(gnunet-identity -d -c test_idp.conf | grep bob | awk '{print $3}')
-EVE_KEY=$(gnunet-identity -d -c test_idp.conf | grep eve | awk '{print $3}')
-
-gnunet-idp -e alice -E 15s -a email -V john@doe.gnu -c test_idp.conf 
-gnunet-idp -e alice -E 15s -a name -V John -c test_idp.conf
-TICKET_BOB=$(gnunet-idp -e alice -i "email,name" -r $BOB_KEY -c test_idp.conf | awk '{print $1}')
-#gnunet-idp -e bob -C $TICKET_BOB -c test_idp.conf
-TICKET_EVE=$(gnunet-idp -e alice -i "email" -r $EVE_KEY -c test_idp.conf | awk '{print $1}')
-
-#echo "Consuming $TICKET"
-#gnunet-idp -e eve -C $TICKET_EVE -c test_idp.conf
-gnunet-idp -e alice -R $TICKET_EVE -c test_idp.conf
-
-#sleep 6
-
-gnunet-idp -e eve -C $TICKET_EVE -c test_idp.conf 2&>1 >/dev/null
-if test $? == 0
-then 
-  echo "Eve can still resolve attributes..."
-  gnunet-arm -e -c test_idp.conf
-  exit 1
-fi
-
-gnunet-arm -e -c test_idp.conf
-gnunet-arm -s -c test_idp.conf 2&>1 > /dev/null
-
-gnunet-idp -e bob -C $TICKET_BOB -c test_idp.conf 2&>1 >/dev/null
-if test $? != 0
-then
-  echo "Bob cannot resolve attributes..."
-  gnunet-arm -e -c test_idp.conf
-  exit 1
-fi
-
-gnunet-arm -e -c test_idp.conf
index 08e9dd156f963b096d2968050758ab284dc689b9..41b2b138239b11c780d3c5461cda79bd9d805c64 100644 (file)
@@ -66,7 +66,7 @@ gnunetinclude_HEADERS = \
   gnunet_hello_lib.h \
   gnunet_helper_lib.h \
   gnunet_identity_service.h \
-  gnunet_identity_provider_service.h \
+  gnunet_reclaim_service.h \
   gnunet_json_lib.h \
   gnunet_jsonapi_lib.h \
   gnunet_jsonapi_util.h \
diff --git a/src/include/gnunet_identity_attribute_lib.h b/src/include/gnunet_identity_attribute_lib.h
deleted file mode 100644 (file)
index eb01f7a..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2017 GNUnet e.V.
-
-     GNUnet is free software: you can redistribute it and/or modify it
-     under the terms of the GNU Affero General Public License as published
-     by the Free Software Foundation, either version 3 of the License,
-     or (at your option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     Affero General Public License for more details.
-    
-     You should have received a copy of the GNU Affero General Public License
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @author Martin Schanzenbach
- *
- * @file
- * Identity attribute definitions
- *
- * @defgroup identity-provider  Identity Provider service
- * @{
- */
-#ifndef GNUNET_IDENTITY_ATTRIBUTE_LIB_H
-#define GNUNET_IDENTITY_ATTRIBUTE_LIB_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "gnunet_util_lib.h"
-
-
-/**
- * No value attribute.
- */
-#define GNUNET_IDENTITY_ATTRIBUTE_TYPE_NONE 0
-
-/**
- * String attribute.
- */
-#define GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING 1
-
-
-
-/**
- * An attribute.
- */
-struct GNUNET_IDENTITY_ATTRIBUTE_Claim
-{
-  /**
-   * The name of the attribute. Note "name" must never be individually
-   * free'd
-   */
-  const char* name;
-
-  /**
-   * Type of Claim
-   */
-  uint32_t type;
-
-  /**
-   * Version
-   */
-  uint32_t version;
-
-  /**
-   * Number of bytes in @e data.
-   */
-  size_t data_size;
-
-  /**
-   * Binary value stored as attribute value.  Note: "data" must never
-   * be individually 'malloc'ed, but instead always points into some
-   * existing data area.
-   */
-  const void *data;
-
-};
-
-struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList
-{
-  /**
-   * List head
-   */
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *list_head;
-
-  /**
-   * List tail
-   */
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *list_tail;
-};
-
-struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry
-{
-  /**
-   * DLL
-   */
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *prev;
-
-  /**
-   * DLL
-   */
-  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *next;
-
-  /**
-   * The attribute claim
-   */
-  struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
-};
-
-/**
- * Create a new attribute claim.
- *
- * @param attr_name the attribute name
- * @param type the attribute type
- * @param data the attribute value
- * @param data_size the attribute value size
- * @return the new attribute
- */
-struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
-GNUNET_IDENTITY_ATTRIBUTE_claim_new (const char* attr_name,
-                                     uint32_t type,
-                                     const void* data,
-                                     size_t data_size);
-
-
-/**
- * Get required size for serialization buffer
- *
- * @param attrs the attribute list to serialize
- *
- * @return the required buffer size
- */
-size_t
-GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
-
-void
-GNUNET_IDENTITY_ATTRIBUTE_list_destroy (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
-
-void
-GNUNET_IDENTITY_ATTRIBUTE_list_add (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
-                                   const char* attr_name,
-                                   uint32_t type,
-                                   const void* data,
-                                   size_t data_size);
-
-/**
- * Serialize an attribute list
- *
- * @param attrs the attribute list to serialize
- * @param result the serialized attribute
- *
- * @return length of serialized data
- */
-size_t
-GNUNET_IDENTITY_ATTRIBUTE_list_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
-                     char *result);
-
-/**
- * Deserialize an attribute list
- *
- * @param data the serialized attribute list
- * @param data_size the length of the serialized data
- *
- * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
- */
-struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *
-GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (const char* data,
-                            size_t data_size);
-
-
-/**
- * Get required size for serialization buffer
- *
- * @param attr the attribute to serialize
- *
- * @return the required buffer size
- */
-size_t
-GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr);
-
-
-
-/**
- * Serialize an attribute
- *
- * @param attr the attribute to serialize
- * @param result the serialized attribute
- *
- * @return length of serialized data
- */
-size_t
-GNUNET_IDENTITY_ATTRIBUTE_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
-                     char *result);
-
-/**
- * Deserialize an attribute
- *
- * @param data the serialized attribute
- * @param data_size the length of the serialized data
- *
- * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
- */
-struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
-GNUNET_IDENTITY_ATTRIBUTE_deserialize (const char* data,
-                       size_t data_size);
-
-struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList*
-GNUNET_IDENTITY_ATTRIBUTE_list_dup (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
-
-/**
- * Convert a type name to the corresponding number
- *
- * @param typename name to convert
- * @return corresponding number, UINT32_MAX on error
- */
-uint32_t
-GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (const char *typename);
-
-/**
- * Convert human-readable version of a 'claim' of an attribute to the binary
- * representation
- *
- * @param type type of the claim
- * @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
- */
-int
-GNUNET_IDENTITY_ATTRIBUTE_string_to_value (uint32_t type,
-                                           const char *s,
-                                           void **data,
-                                           size_t *data_size);
-
-/**
- * Convert the 'claim' of an attribute to a string
- *
- * @param type the type of attribute
- * @param data claim in binary encoding
- * @param data_size number of bytes in @a data
- * @return NULL on error, otherwise human-readable representation of the claim
- */
-char *
-GNUNET_IDENTITY_ATTRIBUTE_value_to_string (uint32_t type,
-                                           const void* data,
-                                           size_t data_size);
-
-/**
- * Convert a type number to the corresponding type string
- *
- * @param type number of a type
- * @return corresponding typestring, NULL on error
- */
-const char*
-GNUNET_IDENTITY_ATTRIBUTE_number_to_typename (uint32_t type);
-
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-
-/* ifndef GNUNET_IDENTITY_ATTRIBUTE_LIB_H */
-#endif
-
-/** @} */ /* end of group identity */
-
-/* end of gnunet_identity_attribute_lib.h */
diff --git a/src/include/gnunet_identity_attribute_plugin.h b/src/include/gnunet_identity_attribute_plugin.h
deleted file mode 100644 (file)
index 7c399c6..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
-     This file is part of GNUnet
-     Copyright (C) 2012, 2013 GNUnet e.V.
-
-     GNUnet is free software: you can redistribute it and/or modify it
-     under the terms of the GNU Affero General Public License as published
-     by the Free Software Foundation, either version 3 of the License,
-     or (at your option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     Affero General Public License for more details.
-    
-     You should have received a copy of the GNU Affero General Public License
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @author Martin Schanzenbach
- *
- * @file
- * Plugin API for the idp database backend
- *
- * @defgroup identity-provider-plugin  IdP service plugin API
- * Plugin API for the idp database backend
- * @{
- */
-#ifndef GNUNET_IDENTITY_ATTRIBUTE_PLUGIN_H
-#define GNUNET_IDENTITY_ATTRIBUTE_PLUGIN_H
-
-#include "gnunet_util_lib.h"
-#include "gnunet_identity_attribute_lib.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-
-/**
- * Function called to convert the binary value @a data of an attribute of
- * type @a type to a human-readable string.
- *
- * @param cls closure
- * @param type type of the attribute
- * @param data value in binary encoding
- * @param data_size number of bytes in @a data
- * @return NULL on error, otherwise human-readable representation of the value
- */
-typedef char * (*GNUNET_IDENTITY_ATTRIBUTE_ValueToStringFunction) (void *cls,
-                                                          uint32_t type,
-                                                          const void *data,
-                                                          size_t data_size);
-
-
-/**
- * Function called to convert human-readable version of the value @a s
- * of an attribute of type @a type to the respective binary
- * representation.
- *
- * @param cls closure
- * @param type type of the attribute
- * @param s human-readable string
- * @param data set to value in binary encoding (will be allocated)
- * @param data_size set to number of bytes in @a data
- * @return #GNUNET_OK on success
- */
-typedef int (*GNUNET_IDENTITY_ATTRIBUTE_StringToValueFunction) (void *cls,
-                                                       uint32_t type,
-                                                       const char *s,
-                                                       void **data,
-                                                       size_t *data_size);
-
-
-/**
- * Function called to convert a type name to the
- * corresponding number.
- *
- * @param cls closure
- * @param typename name to convert
- * @return corresponding number, UINT32_MAX on error
- */
-typedef uint32_t (*GNUNET_IDENTITY_ATTRIBUTE_TypenameToNumberFunction) (void *cls,
-                                                               const char *typename);
-
-
-/**
- * Function called to convert a type number (i.e. 1) to the
- * corresponding type string
- *
- * @param cls closure
- * @param type number of a type to convert
- * @return corresponding typestring, NULL on error
- */
-typedef const char * (*GNUNET_IDENTITY_ATTRIBUTE_NumberToTypenameFunction) (void *cls,
-                                                                   uint32_t type);
-
-
-/**
- * Each plugin is required to return a pointer to a struct of this
- * type as the return value from its entry point.
- */
-struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions
-{
-
-  /**
-   * Closure for all of the callbacks.
-   */
-  void *cls;
-
-  /**
-   * Conversion to string.
-   */
-  GNUNET_IDENTITY_ATTRIBUTE_ValueToStringFunction value_to_string;
-
-  /**
-   * Conversion to binary.
-   */
-  GNUNET_IDENTITY_ATTRIBUTE_StringToValueFunction string_to_value;
-
-  /**
-   * Typename to number.
-   */
-  GNUNET_IDENTITY_ATTRIBUTE_TypenameToNumberFunction typename_to_number;
-
-  /**
-   * Number to typename.
-   */
-  GNUNET_IDENTITY_ATTRIBUTE_NumberToTypenameFunction number_to_typename;
-
-};
-
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-/** @} */  /* end of group */
diff --git a/src/include/gnunet_identity_provider_plugin.h b/src/include/gnunet_identity_provider_plugin.h
deleted file mode 100644 (file)
index 2330066..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-     This file is part of GNUnet
-     Copyright (C) 2012, 2013 GNUnet e.V.
-
-     GNUnet is free software: you can redistribute it and/or modify it
-     under the terms of the GNU Affero General Public License as published
-     by the Free Software Foundation, either version 3 of the License,
-     or (at your option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     Affero General Public License for more details.
-    
-     You should have received a copy of the GNU Affero General Public License
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @author Martin Schanzenbach
- *
- * @file
- * Plugin API for the idp database backend
- *
- * @defgroup identity-provider-plugin  IdP service plugin API
- * Plugin API for the idp database backend
- * @{
- */
-#ifndef GNUNET_IDENTITY_PROVIDER_PLUGIN_H
-#define GNUNET_IDENTITY_PROVIDER_PLUGIN_H
-
-#include "gnunet_util_lib.h"
-#include "gnunet_identity_provider_service.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-
-/**
- * Function called by for each matching ticket.
- *
- * @param cls closure
- * @param ticket the ticket
- */
-typedef void (*GNUNET_IDENTITY_PROVIDER_TicketIterator) (void *cls,
-                                                const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-             const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
-
-
-/**
- * @brief struct returned by the initialization function of the plugin
- */
-struct GNUNET_IDENTITY_PROVIDER_PluginFunctions
-{
-
-  /**
-   * Closure to pass to all plugin functions.
-   */
-  void *cls;
-
-  /**
-   * Store a ticket in the database.
-   *
-   * @param cls closure (internal context for the plugin)
-   * @param ticket the ticket to store
-   * @return #GNUNET_OK on success, else #GNUNET_SYSERR
-   */
-  int (*store_ticket) (void *cls,
-                       const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-      const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
-
-  /**
-   * Delete a ticket from the database.
-   *
-   * @param cls closure (internal context for the plugin)
-   * @param ticket the ticket to store
-   * @return #GNUNET_OK on success, else #GNUNET_SYSERR
-   */
-  int (*delete_ticket) (void *cls,
-                       const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket);
-
-
-
-  /**
-   * Iterate over all tickets
-   *
-   * @param cls closure (internal context for the plugin)
-   * @param identity the identity
-   * @param audience GNUNET_YES if the identity is the audience of the ticket
-   *                 else it is considered the issuer
-   * @param iter function to call with the result
-   * @param iter_cls closure for @a iter
-   * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
-   */
-  int (*iterate_tickets) (void *cls,
-                         const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-        int audience,
-                         uint64_t offset,
-                         GNUNET_IDENTITY_PROVIDER_TicketIterator iter, void *iter_cls);
-
-  int (*get_ticket_attributes) (void* cls,
-                                const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                                GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
-                                void *iter_cls);
-};
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-/** @} */  /* end of group */
diff --git a/src/include/gnunet_identity_provider_service.h b/src/include/gnunet_identity_provider_service.h
deleted file mode 100644 (file)
index 0c72556..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2016 GNUnet e.V.
-
-     GNUnet is free software: you can redistribute it and/or modify it
-     under the terms of the GNU Affero General Public License as published
-     by the Free Software Foundation, either version 3 of the License,
-     or (at your option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     Affero General Public License for more details.
-    
-     You should have received a copy of the GNU Affero General Public License
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @author Martin Schanzenbach
- *
- * @file
- * Identity provider service; implements identity provider for GNUnet
- *
- * @defgroup identity-provider  Identity Provider service
- * @{
- */
-#ifndef GNUNET_IDENTITY_PROVIDER_SERVICE_H
-#define GNUNET_IDENTITY_PROVIDER_SERVICE_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "gnunet_util_lib.h"
-#include "gnunet_identity_attribute_lib.h"
-
-/**
- * Version number of GNUnet Identity Provider API.
- */
-#define GNUNET_IDENTITY_PROVIDER_VERSION 0x00000000
-
-/**
- * Handle to access the identity service.
- */
-struct GNUNET_IDENTITY_PROVIDER_Handle;
-
-/**
- * Handle for a token.
- */
-struct GNUNET_IDENTITY_PROVIDER_Token;
-
-/**
- * The ticket
- */
-struct GNUNET_IDENTITY_PROVIDER_Ticket
-{
-  /**
-   * The ticket issuer
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
-
-  /**
-   * The ticket audience
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey audience;
-
-  /**
-   * The ticket random (NBO)
-   */
-  uint64_t rnd;
-};
-
-/**
- * Handle for an operation with the identity provider service.
- */
-struct GNUNET_IDENTITY_PROVIDER_Operation;
-
-
-/**
- * Connect to the identity provider service.
- *
- * @param cfg Configuration to contact the identity provider service.
- * @return handle to communicate with identity provider service
- */
-struct GNUNET_IDENTITY_PROVIDER_Handle *
-GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
-
-/**
- * Continuation called to notify client about result of the
- * operation.
- *
- * @param cls closure
- * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
- *                #GNUNET_NO if content was already there or not found
- *                #GNUNET_YES (or other positive value) on success
- * @param emsg NULL on success, otherwise an error message
- */
-typedef void
-(*GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus) (void *cls,
-                                            int32_t success,
-                                            const char *emsg);
-
-
-/**
- * Store an attribute.  If the attribute is already present,
- * it is replaced with the new attribute.
- *
- * @param h handle to the identity provider
- * @param pkey private key of the identity
- * @param attr the attribute
- * @param exp_interval the relative expiration interval for the attribute
- * @param cont continuation to call when done
- * @param cont_cls closure for @a cont
- * @return handle to abort the request
- */
-struct GNUNET_IDENTITY_PROVIDER_Operation *
-GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
-                                          const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
-                                          const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
-                                          const struct GNUNET_TIME_Relative *exp_interval,
-                                          GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont,
-                                          void *cont_cls);
-
-
-/**
- * Process an attribute that was stored in the idp.
- *
- * @param cls closure
- * @param identity the identity
- * @param attr the attribute
- */
-typedef void
-(*GNUNET_IDENTITY_PROVIDER_AttributeResult) (void *cls,
-                                   const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-                                   const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr);
-
-
-
-/**
- * List all attributes for a local identity. 
- * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle`
- * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and
- * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once
- * immediately, and then again after
- * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked.
- *
- * On error (disconnect), @a error_cb will be invoked.
- * On normal completion, @a finish_cb proc will be
- * invoked.
- *
- * @param h handle to the idp
- * @param identity identity to access
- * @param error_cb function to call on error (i.e. disconnect),
- *        the handle is afterwards invalid
- * @param error_cb_cls closure for @a error_cb
- * @param proc function to call on each attribute; it
- *        will be called repeatedly with a value (if available)
- * @param proc_cls closure for @a proc
- * @param finish_cb function to call on completion
- *        the handle is afterwards invalid
- * @param finish_cb_cls closure for @a finish_cb
- * @return an iterator handle to use for iteration
- */
-struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *
-GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
-                                               const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
-                                               GNUNET_SCHEDULER_TaskCallback error_cb,
-                                               void *error_cb_cls,
-                                               GNUNET_IDENTITY_PROVIDER_AttributeResult proc,
-                                               void *proc_cls,
-                                               GNUNET_SCHEDULER_TaskCallback finish_cb,
-                                               void *finish_cb_cls);
-
-
-/**
- * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start
- * for the next record.
- *
- * @param it the iterator
- */
-void
-GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it);
-
-
-/**
- * Stops iteration and releases the idp handle for further calls.  Must
- * be called on any iteration that has not yet completed prior to calling
- * #GNUNET_IDENTITY_PROVIDER_disconnect.
- *
- * @param it the iterator
- */
-void
-GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it);
-
-
-/**
- * Method called when a token has been issued.
- * On success returns a ticket that can be given to the audience to retrive the
- * token
- *
- * @param cls closure
- * @param ticket the ticket
- */
-typedef void
-(*GNUNET_IDENTITY_PROVIDER_TicketCallback)(void *cls,
-                            const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket);
-
-/**
- * Issues a ticket to another identity. The identity may use
- * GNUNET_IDENTITY_PROVIDER_ticket_consume to consume the ticket
- * and retrieve the attributes specified in the AttributeList.
- *
- * @param h the identity provider to use
- * @param iss the issuing identity
- * @param rp the subject of the ticket (the relying party)
- * @param attrs the attributes that the relying party is given access to
- * @param cb the callback
- * @param cb_cls the callback closure
- * @return handle to abort the operation
- */
-struct GNUNET_IDENTITY_PROVIDER_Operation *
-GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
-                                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
-                                       const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
-                                       const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
-                                       GNUNET_IDENTITY_PROVIDER_TicketCallback cb,
-                                       void *cb_cls);
-
-/**
- * Revoked an issued ticket. The relying party will be unable to retrieve
- * updated attributes.
- *
- * @param h the identity provider to use
- * @param identity the issuing identity
- * @param ticket the ticket to revoke
- * @param cb the callback
- * @param cb_cls the callback closure
- * @return handle to abort the operation
- */
-struct GNUNET_IDENTITY_PROVIDER_Operation *
-GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
-                                        const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
-                                        const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                                        GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb,
-                                        void *cb_cls);
-
-
-
-/**
- * Consumes an issued ticket. The ticket is persisted
- * and used to retrieve identity information from the issuer
- *
- * @param h the identity provider to use
- * @param identity the identity that is the subject of the issued ticket (the audience)
- * @param ticket the issued ticket to consume
- * @param cb the callback to call
- * @param cb_cls the callback closure
- * @return handle to abort the operation
- */
-struct GNUNET_IDENTITY_PROVIDER_Operation *
-GNUNET_IDENTITY_PROVIDER_ticket_consume (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
-                                         const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
-                                         const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                                         GNUNET_IDENTITY_PROVIDER_AttributeResult cb,
-                                         void *cb_cls);
-
-/**
- * Lists all tickets that have been issued to remote
- * identites (relying parties)
- *
- * @param h the identity provider to use
- * @param identity the issuing identity
- * @param error_cb function to call on error (i.e. disconnect),
- *        the handle is afterwards invalid
- * @param error_cb_cls closure for @a error_cb
- * @param proc function to call on each ticket; it
- *        will be called repeatedly with a value (if available)
- * @param proc_cls closure for @a proc
- * @param finish_cb function to call on completion
- *        the handle is afterwards invalid
- * @param finish_cb_cls closure for @a finish_cb
- * @return an iterator handle to use for iteration
- */
-struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
-GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
-                                                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
-                                                 GNUNET_SCHEDULER_TaskCallback error_cb,
-                                                 void *error_cb_cls,
-                                                 GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
-                                                 void *proc_cls,
-                                                 GNUNET_SCHEDULER_TaskCallback finish_cb,
-                                                 void *finish_cb_cls);
-
-/**
- * Lists all tickets that have been issued to remote
- * identites (relying parties)
- *
- * @param h the identity provider to use
- * @param identity the issuing identity
- * @param error_cb function to call on error (i.e. disconnect),
- *        the handle is afterwards invalid
- * @param error_cb_cls closure for @a error_cb
- * @param proc function to call on each ticket; it
- *        will be called repeatedly with a value (if available)
- * @param proc_cls closure for @a proc
- * @param finish_cb function to call on completion
- *        the handle is afterwards invalid
- * @param finish_cb_cls closure for @a finish_cb
- * @return an iterator handle to use for iteration
- */
-struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
-GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
-                                                    const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-                                                    GNUNET_SCHEDULER_TaskCallback error_cb,
-                                                    void *error_cb_cls,
-                                                    GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
-                                                    void *proc_cls,
-                                                    GNUNET_SCHEDULER_TaskCallback finish_cb,
-                                                    void *finish_cb_cls);
-
-/**
- * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start
- * for the next record.
- *
- * @param it the iterator
- */
-void
-GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it);
-
-/**
- * Stops iteration and releases the idp handle for further calls.  Must
- * be called on any iteration that has not yet completed prior to calling
- * #GNUNET_IDENTITY_PROVIDER_disconnect.
- *
- * @param it the iterator
- */
-void
-GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it);
-
-/**
- * Disconnect from identity provider service.
- *
- * @param h identity provider service to disconnect
- */
-void
-GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h);
-
-
-/**
- * Cancel an identity provider operation.  Note that the operation MAY still
- * be executed; this merely cancels the continuation; if the request
- * was already transmitted, the service may still choose to complete
- * the operation.
- *
- * @param op operation to cancel
- */
-void
-GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op);
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-
-/* ifndef GNUNET_IDENTITY_PROVIDER_SERVICE_H */
-#endif
-
-/** @} */ /* end of group identity */
-
-/* end of gnunet_identity_provider_service.h */
index 36aa424b48cdeeb29244a2ed4586db4a6b491cb0..4400db7e1c6177f4813082518cb30f96d5374c37 100644 (file)
@@ -2656,35 +2656,35 @@ extern "C"
  *
  * IDENTITY PROVIDER MESSAGE TYPES
  */
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE 961
+#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE 961
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE 962
+#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE_RESPONSE 962
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START 963
+#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START 963
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP 964
+#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP 964
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT 965
+#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT 965
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT 966
+#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT 966
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET 967
+#define GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET 967
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT 968
+#define GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT 968
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET 969
+#define GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET 969
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT 970
+#define GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT 970
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET 971
+#define GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET 971
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT 972
+#define GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT 972
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START 973
+#define GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START 973
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP 974
+#define GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP 974
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT 975
+#define GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT 975
 
 /**************************************************
  *
diff --git a/src/include/gnunet_reclaim_attribute_lib.h b/src/include/gnunet_reclaim_attribute_lib.h
new file mode 100644 (file)
index 0000000..df5356d
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2017 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @author Martin Schanzenbach
+ *
+ * @file
+ * Identity attribute definitions
+ *
+ * @defgroup identity-provider  Identity Provider service
+ * @{
+ */
+#ifndef GNUNET_RECLAIM_ATTRIBUTE_LIB_H
+#define GNUNET_RECLAIM_ATTRIBUTE_LIB_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "gnunet_util_lib.h"
+
+
+/**
+ * No value attribute.
+ */
+#define GNUNET_RECLAIM_ATTRIBUTE_TYPE_NONE 0
+
+/**
+ * String attribute.
+ */
+#define GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING 1
+
+
+
+/**
+ * An attribute.
+ */
+struct GNUNET_RECLAIM_ATTRIBUTE_Claim
+{
+  /**
+   * The name of the attribute. Note "name" must never be individually
+   * free'd
+   */
+  const char* name;
+
+  /**
+   * Type of Claim
+   */
+  uint32_t type;
+
+  /**
+   * Version
+   */
+  uint32_t version;
+
+  /**
+   * Number of bytes in @e data.
+   */
+  size_t data_size;
+
+  /**
+   * Binary value stored as attribute value.  Note: "data" must never
+   * be individually 'malloc'ed, but instead always points into some
+   * existing data area.
+   */
+  const void *data;
+
+};
+
+struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList
+{
+  /**
+   * List head
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *list_head;
+
+  /**
+   * List tail
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *list_tail;
+};
+
+struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry
+{
+  /**
+   * DLL
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *prev;
+
+  /**
+   * DLL
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *next;
+
+  /**
+   * The attribute claim
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
+};
+
+/**
+ * Create a new attribute claim.
+ *
+ * @param attr_name the attribute name
+ * @param type the attribute type
+ * @param data the attribute value
+ * @param data_size the attribute value size
+ * @return the new attribute
+ */
+struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
+GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char* attr_name,
+                                     uint32_t type,
+                                     const void* data,
+                                     size_t data_size);
+
+
+/**
+ * Get required size for serialization buffer
+ *
+ * @param attrs the attribute list to serialize
+ *
+ * @return the required buffer size
+ */
+size_t
+GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs);
+
+void
+GNUNET_RECLAIM_ATTRIBUTE_list_destroy (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs);
+
+void
+GNUNET_RECLAIM_ATTRIBUTE_list_add (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+                                   const char* attr_name,
+                                   uint32_t type,
+                                   const void* data,
+                                   size_t data_size);
+
+/**
+ * Serialize an attribute list
+ *
+ * @param attrs the attribute list to serialize
+ * @param result the serialized attribute
+ *
+ * @return length of serialized data
+ */
+size_t
+GNUNET_RECLAIM_ATTRIBUTE_list_serialize (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+                     char *result);
+
+/**
+ * Deserialize an attribute list
+ *
+ * @param data the serialized attribute list
+ * @param data_size the length of the serialized data
+ *
+ * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
+ */
+struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
+GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (const char* data,
+                            size_t data_size);
+
+
+/**
+ * Get required size for serialization buffer
+ *
+ * @param attr the attribute to serialize
+ *
+ * @return the required buffer size
+ */
+size_t
+GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr);
+
+
+
+/**
+ * Serialize an attribute
+ *
+ * @param attr the attribute to serialize
+ * @param result the serialized attribute
+ *
+ * @return length of serialized data
+ */
+size_t
+GNUNET_RECLAIM_ATTRIBUTE_serialize (const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
+                     char *result);
+
+/**
+ * Deserialize an attribute
+ *
+ * @param data the serialized attribute
+ * @param data_size the length of the serialized data
+ *
+ * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
+ */
+struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
+GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char* data,
+                       size_t data_size);
+
+struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList*
+GNUNET_RECLAIM_ATTRIBUTE_list_dup (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs);
+
+/**
+ * Convert a type name to the corresponding number
+ *
+ * @param typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+uint32_t
+GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (const char *typename);
+
+/**
+ * Convert human-readable version of a 'claim' of an attribute to the binary
+ * representation
+ *
+ * @param type type of the claim
+ * @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
+ */
+int
+GNUNET_RECLAIM_ATTRIBUTE_string_to_value (uint32_t type,
+                                           const char *s,
+                                           void **data,
+                                           size_t *data_size);
+
+/**
+ * Convert the 'claim' of an attribute to a string
+ *
+ * @param type the type of attribute
+ * @param data claim in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the claim
+ */
+char *
+GNUNET_RECLAIM_ATTRIBUTE_value_to_string (uint32_t type,
+                                           const void* data,
+                                           size_t data_size);
+
+/**
+ * Convert a type number to the corresponding type string
+ *
+ * @param type number of a type
+ * @return corresponding typestring, NULL on error
+ */
+const char*
+GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (uint32_t type);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+
+/* ifndef GNUNET_RECLAIM_ATTRIBUTE_LIB_H */
+#endif
+
+/** @} */ /* end of group identity */
+
+/* end of gnunet_reclaim_attribute_lib.h */
diff --git a/src/include/gnunet_reclaim_attribute_plugin.h b/src/include/gnunet_reclaim_attribute_plugin.h
new file mode 100644 (file)
index 0000000..cf0bb14
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2012, 2013 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @author Martin Schanzenbach
+ *
+ * @file
+ * Plugin API for the idp database backend
+ *
+ * @defgroup identity-provider-plugin  IdP service plugin API
+ * Plugin API for the idp database backend
+ * @{
+ */
+#ifndef GNUNET_RECLAIM_ATTRIBUTE_PLUGIN_H
+#define GNUNET_RECLAIM_ATTRIBUTE_PLUGIN_H
+
+#include "gnunet_util_lib.h"
+#include "gnunet_reclaim_attribute_lib.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+
+/**
+ * Function called to convert the binary value @a data of an attribute of
+ * type @a type to a human-readable string.
+ *
+ * @param cls closure
+ * @param type type of the attribute
+ * @param data value in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the value
+ */
+typedef char * (*GNUNET_RECLAIM_ATTRIBUTE_ValueToStringFunction) (void *cls,
+                                                          uint32_t type,
+                                                          const void *data,
+                                                          size_t data_size);
+
+
+/**
+ * Function called to convert human-readable version of the value @a s
+ * of an attribute of type @a type to the respective binary
+ * representation.
+ *
+ * @param cls closure
+ * @param type type of the attribute
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+typedef int (*GNUNET_RECLAIM_ATTRIBUTE_StringToValueFunction) (void *cls,
+                                                       uint32_t type,
+                                                       const char *s,
+                                                       void **data,
+                                                       size_t *data_size);
+
+
+/**
+ * Function called to convert a type name to the
+ * corresponding number.
+ *
+ * @param cls closure
+ * @param typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+typedef uint32_t (*GNUNET_RECLAIM_ATTRIBUTE_TypenameToNumberFunction) (void *cls,
+                                                               const char *typename);
+
+
+/**
+ * Function called to convert a type number (i.e. 1) to the
+ * corresponding type string
+ *
+ * @param cls closure
+ * @param type number of a type to convert
+ * @return corresponding typestring, NULL on error
+ */
+typedef const char * (*GNUNET_RECLAIM_ATTRIBUTE_NumberToTypenameFunction) (void *cls,
+                                                                   uint32_t type);
+
+
+/**
+ * Each plugin is required to return a pointer to a struct of this
+ * type as the return value from its entry point.
+ */
+struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions
+{
+
+  /**
+   * Closure for all of the callbacks.
+   */
+  void *cls;
+
+  /**
+   * Conversion to string.
+   */
+  GNUNET_RECLAIM_ATTRIBUTE_ValueToStringFunction value_to_string;
+
+  /**
+   * Conversion to binary.
+   */
+  GNUNET_RECLAIM_ATTRIBUTE_StringToValueFunction string_to_value;
+
+  /**
+   * Typename to number.
+   */
+  GNUNET_RECLAIM_ATTRIBUTE_TypenameToNumberFunction typename_to_number;
+
+  /**
+   * Number to typename.
+   */
+  GNUNET_RECLAIM_ATTRIBUTE_NumberToTypenameFunction number_to_typename;
+
+};
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/** @} */  /* end of group */
diff --git a/src/include/gnunet_reclaim_plugin.h b/src/include/gnunet_reclaim_plugin.h
new file mode 100644 (file)
index 0000000..c400af6
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2012, 2013 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @author Martin Schanzenbach
+ *
+ * @file
+ * Plugin API for the idp database backend
+ *
+ * @defgroup reclaim-plugin  IdP service plugin API
+ * Plugin API for the idp database backend
+ * @{
+ */
+#ifndef GNUNET_RECLAIM_PLUGIN_H
+#define GNUNET_RECLAIM_PLUGIN_H
+
+#include "gnunet_util_lib.h"
+#include "gnunet_reclaim_service.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+
+/**
+ * Function called by for each matching ticket.
+ *
+ * @param cls closure
+ * @param ticket the ticket
+ */
+typedef void (*GNUNET_RECLAIM_TicketIterator) (void *cls,
+                                                const struct GNUNET_RECLAIM_Ticket *ticket,
+             const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs);
+
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct GNUNET_RECLAIM_PluginFunctions
+{
+
+  /**
+   * Closure to pass to all plugin functions.
+   */
+  void *cls;
+
+  /**
+   * Store a ticket in the database.
+   *
+   * @param cls closure (internal context for the plugin)
+   * @param ticket the ticket to store
+   * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+   */
+  int (*store_ticket) (void *cls,
+                       const struct GNUNET_RECLAIM_Ticket *ticket,
+      const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs);
+
+  /**
+   * Delete a ticket from the database.
+   *
+   * @param cls closure (internal context for the plugin)
+   * @param ticket the ticket to store
+   * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+   */
+  int (*delete_ticket) (void *cls,
+                       const struct GNUNET_RECLAIM_Ticket *ticket);
+
+
+
+  /**
+   * Iterate over all tickets
+   *
+   * @param cls closure (internal context for the plugin)
+   * @param identity the identity
+   * @param audience GNUNET_YES if the identity is the audience of the ticket
+   *                 else it is considered the issuer
+   * @param iter function to call with the result
+   * @param iter_cls closure for @a iter
+   * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
+   */
+  int (*iterate_tickets) (void *cls,
+                         const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+        int audience,
+                         uint64_t offset,
+                         GNUNET_RECLAIM_TicketIterator iter, void *iter_cls);
+
+  int (*get_ticket_attributes) (void* cls,
+                                const struct GNUNET_RECLAIM_Ticket *ticket,
+                                GNUNET_RECLAIM_TicketIterator iter,
+                                void *iter_cls);
+};
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/** @} */  /* end of group */
diff --git a/src/include/gnunet_reclaim_service.h b/src/include/gnunet_reclaim_service.h
new file mode 100644 (file)
index 0000000..7e668cd
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2016 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @author Martin Schanzenbach
+ *
+ * @file
+ * Identity provider service; implements identity provider for GNUnet
+ *
+ * @defgroup reclaim  Identity Provider service
+ * @{
+ */
+#ifndef GNUNET_RECLAIM_SERVICE_H
+#define GNUNET_RECLAIM_SERVICE_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "gnunet_util_lib.h"
+#include "gnunet_reclaim_attribute_lib.h"
+
+/**
+ * Version number of GNUnet Identity Provider API.
+ */
+#define GNUNET_RECLAIM_VERSION 0x00000000
+
+/**
+ * Handle to access the identity service.
+ */
+struct GNUNET_RECLAIM_Handle;
+
+/**
+ * Handle for a token.
+ */
+struct GNUNET_RECLAIM_Token;
+
+/**
+ * The ticket
+ */
+struct GNUNET_RECLAIM_Ticket
+{
+  /**
+   * The ticket issuer
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
+
+  /**
+   * The ticket audience
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey audience;
+
+  /**
+   * The ticket random (NBO)
+   */
+  uint64_t rnd;
+};
+
+/**
+ * Handle for an operation with the identity provider service.
+ */
+struct GNUNET_RECLAIM_Operation;
+
+
+/**
+ * Connect to the identity provider service.
+ *
+ * @param cfg Configuration to contact the identity provider service.
+ * @return handle to communicate with identity provider service
+ */
+struct GNUNET_RECLAIM_Handle *
+GNUNET_RECLAIM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
+
+/**
+ * Continuation called to notify client about result of the
+ * operation.
+ *
+ * @param cls closure
+ * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
+ *                #GNUNET_NO if content was already there or not found
+ *                #GNUNET_YES (or other positive value) on success
+ * @param emsg NULL on success, otherwise an error message
+ */
+typedef void
+(*GNUNET_RECLAIM_ContinuationWithStatus) (void *cls,
+                                            int32_t success,
+                                            const char *emsg);
+
+
+/**
+ * Store an attribute.  If the attribute is already present,
+ * it is replaced with the new attribute.
+ *
+ * @param h handle to the identity provider
+ * @param pkey private key of the identity
+ * @param attr the attribute
+ * @param exp_interval the relative expiration interval for the attribute
+ * @param cont continuation to call when done
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the request
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_attribute_store (struct GNUNET_RECLAIM_Handle *h,
+                                          const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+                                          const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
+                                          const struct GNUNET_TIME_Relative *exp_interval,
+                                          GNUNET_RECLAIM_ContinuationWithStatus cont,
+                                          void *cont_cls);
+
+
+/**
+ * Process an attribute that was stored in the idp.
+ *
+ * @param cls closure
+ * @param identity the identity
+ * @param attr the attribute
+ */
+typedef void
+(*GNUNET_RECLAIM_AttributeResult) (void *cls,
+                                   const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+                                   const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr);
+
+
+
+/**
+ * List all attributes for a local identity. 
+ * This MUST lock the `struct GNUNET_RECLAIM_Handle`
+ * for any other calls than #GNUNET_RECLAIM_get_attributes_next() and
+ * #GNUNET_RECLAIM_get_attributes_stop. @a proc will be called once
+ * immediately, and then again after
+ * #GNUNET_RECLAIM_get_attributes_next() is invoked.
+ *
+ * On error (disconnect), @a error_cb will be invoked.
+ * On normal completion, @a finish_cb proc will be
+ * invoked.
+ *
+ * @param h handle to the idp
+ * @param identity identity to access
+ * @param error_cb function to call on error (i.e. disconnect),
+ *        the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each attribute; it
+ *        will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ *        the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
+ */
+struct GNUNET_RECLAIM_AttributeIterator *
+GNUNET_RECLAIM_get_attributes_start (struct GNUNET_RECLAIM_Handle *h,
+                                               const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                               GNUNET_SCHEDULER_TaskCallback error_cb,
+                                               void *error_cb_cls,
+                                               GNUNET_RECLAIM_AttributeResult proc,
+                                               void *proc_cls,
+                                               GNUNET_SCHEDULER_TaskCallback finish_cb,
+                                               void *finish_cb_cls);
+
+
+/**
+ * Calls the record processor specified in #GNUNET_RECLAIM_get_attributes_start
+ * for the next record.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_RECLAIM_get_attributes_next (struct GNUNET_RECLAIM_AttributeIterator *it);
+
+
+/**
+ * Stops iteration and releases the idp handle for further calls.  Must
+ * be called on any iteration that has not yet completed prior to calling
+ * #GNUNET_RECLAIM_disconnect.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it);
+
+
+/**
+ * Method called when a token has been issued.
+ * On success returns a ticket that can be given to the audience to retrive the
+ * token
+ *
+ * @param cls closure
+ * @param ticket the ticket
+ */
+typedef void
+(*GNUNET_RECLAIM_TicketCallback)(void *cls,
+                            const struct GNUNET_RECLAIM_Ticket *ticket);
+
+/**
+ * Issues a ticket to another identity. The identity may use
+ * GNUNET_RECLAIM_ticket_consume to consume the ticket
+ * and retrieve the attributes specified in the AttributeList.
+ *
+ * @param h the identity provider to use
+ * @param iss the issuing identity
+ * @param rp the subject of the ticket (the relying party)
+ * @param attrs the attributes that the relying party is given access to
+ * @param cb the callback
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_ticket_issue (struct GNUNET_RECLAIM_Handle *h,
+                                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
+                                       const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
+                                       const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+                                       GNUNET_RECLAIM_TicketCallback cb,
+                                       void *cb_cls);
+
+/**
+ * Revoked an issued ticket. The relying party will be unable to retrieve
+ * updated attributes.
+ *
+ * @param h the identity provider to use
+ * @param identity the issuing identity
+ * @param ticket the ticket to revoke
+ * @param cb the callback
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_ticket_revoke (struct GNUNET_RECLAIM_Handle *h,
+                                        const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                        const struct GNUNET_RECLAIM_Ticket *ticket,
+                                        GNUNET_RECLAIM_ContinuationWithStatus cb,
+                                        void *cb_cls);
+
+
+
+/**
+ * Consumes an issued ticket. The ticket is persisted
+ * and used to retrieve identity information from the issuer
+ *
+ * @param h the identity provider to use
+ * @param identity the identity that is the subject of the issued ticket (the audience)
+ * @param ticket the issued ticket to consume
+ * @param cb the callback to call
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_ticket_consume (struct GNUNET_RECLAIM_Handle *h,
+                                         const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                         const struct GNUNET_RECLAIM_Ticket *ticket,
+                                         GNUNET_RECLAIM_AttributeResult cb,
+                                         void *cb_cls);
+
+/**
+ * Lists all tickets that have been issued to remote
+ * identites (relying parties)
+ *
+ * @param h the identity provider to use
+ * @param identity the issuing identity
+ * @param error_cb function to call on error (i.e. disconnect),
+ *        the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each ticket; it
+ *        will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ *        the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
+ */
+struct GNUNET_RECLAIM_TicketIterator *
+GNUNET_RECLAIM_ticket_iteration_start (struct GNUNET_RECLAIM_Handle *h,
+                                                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                                 GNUNET_SCHEDULER_TaskCallback error_cb,
+                                                 void *error_cb_cls,
+                                                 GNUNET_RECLAIM_TicketCallback proc,
+                                                 void *proc_cls,
+                                                 GNUNET_SCHEDULER_TaskCallback finish_cb,
+                                                 void *finish_cb_cls);
+
+/**
+ * Lists all tickets that have been issued to remote
+ * identites (relying parties)
+ *
+ * @param h the identity provider to use
+ * @param identity the issuing identity
+ * @param error_cb function to call on error (i.e. disconnect),
+ *        the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each ticket; it
+ *        will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ *        the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
+ */
+struct GNUNET_RECLAIM_TicketIterator *
+GNUNET_RECLAIM_ticket_iteration_start_rp (struct GNUNET_RECLAIM_Handle *h,
+                                                    const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+                                                    GNUNET_SCHEDULER_TaskCallback error_cb,
+                                                    void *error_cb_cls,
+                                                    GNUNET_RECLAIM_TicketCallback proc,
+                                                    void *proc_cls,
+                                                    GNUNET_SCHEDULER_TaskCallback finish_cb,
+                                                    void *finish_cb_cls);
+
+/**
+ * Calls the record processor specified in #GNUNET_RECLAIM_ticket_iteration_start
+ * for the next record.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_RECLAIM_ticket_iteration_next (struct GNUNET_RECLAIM_TicketIterator *it);
+
+/**
+ * Stops iteration and releases the idp handle for further calls.  Must
+ * be called on any iteration that has not yet completed prior to calling
+ * #GNUNET_RECLAIM_disconnect.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_RECLAIM_ticket_iteration_stop (struct GNUNET_RECLAIM_TicketIterator *it);
+
+/**
+ * Disconnect from identity provider service.
+ *
+ * @param h identity provider service to disconnect
+ */
+void
+GNUNET_RECLAIM_disconnect (struct GNUNET_RECLAIM_Handle *h);
+
+
+/**
+ * Cancel an identity provider operation.  Note that the operation MAY still
+ * be executed; this merely cancels the continuation; if the request
+ * was already transmitted, the service may still choose to complete
+ * the operation.
+ *
+ * @param op operation to cancel
+ */
+void
+GNUNET_RECLAIM_cancel (struct GNUNET_RECLAIM_Operation *op);
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+
+/* ifndef GNUNET_RECLAIM_SERVICE_H */
+#endif
+
+/** @} */ /* end of group identity */
+
+/* end of gnunet_reclaim_service.h */
diff --git a/src/reclaim-attribute/Makefile.am b/src/reclaim-attribute/Makefile.am
new file mode 100644 (file)
index 0000000..7db2925
--- /dev/null
@@ -0,0 +1,44 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+plugindir = $(libdir)/gnunet
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+if MINGW
+  WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+endif
+
+if USE_COVERAGE
+  AM_CFLAGS = --coverage -O0
+  XLIBS = -lgcov
+endif
+
+lib_LTLIBRARIES = \
+  libgnunetreclaimattribute.la
+
+libgnunetreclaimattribute_la_SOURCES = \
+  reclaim_attribute.c
+libgnunetreclaimattribute_la_LIBADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(GN_LIBINTL)
+libgnunetreclaimattribute_la_LDFLAGS = \
+  $(GN_LIB_LDFLAGS) $(WINFLAGS) \
+  -version-info 0:0:0
+
+
+plugin_LTLIBRARIES = \
+  libgnunet_plugin_reclaim_attribute_gnuid.la
+
+
+libgnunet_plugin_reclaim_attribute_gnuid_la_SOURCES = \
+  plugin_reclaim_attribute_gnuid.c
+libgnunet_plugin_reclaim_attribute_gnuid_la_LIBADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(LTLIBINTL)
+libgnunet_plugin_reclaim_attribute_gnuid_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
diff --git a/src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c b/src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c
new file mode 100644 (file)
index 0000000..48afc07
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2013, 2014, 2016 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file reclaim-attribute/plugin_reclaim_attribute_gnuid.c
+ * @brief identity attribute plugin to provide the API for fundamental 
+ *                 attribute types.
+ *
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_reclaim_attribute_plugin.h"
+#include <inttypes.h>
+
+
+/**
+ * Convert the 'value' of an attribute to a string.
+ *
+ * @param cls closure, unused
+ * @param type type of the attribute
+ * @param data value in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the value
+ */
+static char *
+gnuid_value_to_string (void *cls,
+                     uint32_t type,
+                     const void *data,
+                     size_t data_size)
+{
+
+  switch (type)
+  {
+  case GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING:
+    return GNUNET_strndup (data, data_size);
+  default:
+    return NULL;
+  }
+}
+
+
+/**
+ * Convert human-readable version of a 'value' of an attribute to the binary
+ * representation.
+ *
+ * @param cls closure, unused
+ * @param type type of the attribute
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+static int
+gnuid_string_to_value (void *cls,
+                     uint32_t type,
+                     const char *s,
+                     void **data,
+                     size_t *data_size)
+{
+  if (NULL == s)
+    return GNUNET_SYSERR;
+  switch (type)
+  {
+
+    case GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING:
+      *data = GNUNET_strdup (s);
+      *data_size = strlen (s);
+      return GNUNET_OK;
+    default:
+      return GNUNET_SYSERR;
+  }
+}
+
+
+/**
+ * Mapping of attribute type numbers to human-readable
+ * attribute type names.
+ */
+static struct {
+  const char *name;
+  uint32_t number;
+} gnuid_name_map[] = {
+  { "STRING",  GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING },
+  { NULL, UINT32_MAX }
+};
+
+
+/**
+ * Convert a type name to the corresponding number.
+ *
+ * @param cls closure, unused
+ * @param gnuid_typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+static uint32_t
+gnuid_typename_to_number (void *cls,
+                        const char *gnuid_typename)
+{
+  unsigned int i;
+
+  i=0;
+  while ( (NULL != gnuid_name_map[i].name) &&
+          (0 != strcasecmp (gnuid_typename,
+                            gnuid_name_map[i].name)) )
+    i++;
+  return gnuid_name_map[i].number;
+}
+
+
+/**
+ * Convert a type number (i.e. 1) to the corresponding type string
+ *
+ * @param cls closure, unused
+ * @param type number of a type to convert
+ * @return corresponding typestring, NULL on error
+ */
+static const char *
+gnuid_number_to_typename (void *cls,
+                        uint32_t type)
+{
+  unsigned int i;
+
+  i=0;
+  while ( (NULL != gnuid_name_map[i].name) &&
+          (type != gnuid_name_map[i].number) )
+    i++;
+  return gnuid_name_map[i].name;
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls NULL
+ * @return the exported block API
+ */
+void *
+libgnunet_plugin_reclaim_attribute_gnuid_init (void *cls)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api;
+
+  api = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions);
+  api->value_to_string = &gnuid_value_to_string;
+  api->string_to_value = &gnuid_string_to_value;
+  api->typename_to_number = &gnuid_typename_to_number;
+  api->number_to_typename = &gnuid_number_to_typename;
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the return value from #libgnunet_plugin_block_test_init()
+ * @return NULL
+ */
+void *
+libgnunet_plugin_reclaim_attribute_gnuid_done (void *cls)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api = cls;
+
+  GNUNET_free (api);
+  return NULL;
+}
+
+/* end of plugin_reclaim_attribute_type_gnuid.c */
diff --git a/src/reclaim-attribute/reclaim_attribute.c b/src/reclaim-attribute/reclaim_attribute.c
new file mode 100644 (file)
index 0000000..74d668e
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2010-2015 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      or (at your option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      Affero General Public License for more details.
+     
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file reclaim-attribute/reclaim_attribute.c
+ * @brief helper library to manage identity attributes
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "reclaim_attribute.h"
+#include "gnunet_reclaim_attribute_plugin.h"
+
+/**
+ * Handle for a plugin
+ */
+struct Plugin
+{
+  /**
+   * Name of the plugin
+   */
+  char *library_name;
+
+  /**
+   * Plugin API
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api;
+};
+
+/**
+ * Plugins
+ */
+static struct Plugin **attr_plugins;
+
+/**
+ * Number of plugins
+ */
+static unsigned int num_plugins;
+
+/**
+ * Init canary
+ */
+static int initialized;
+
+/**
+ * Add a plugin
+ */
+static void
+add_plugin (void* cls,
+            const char *library_name,
+            void *lib_ret)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api = lib_ret;
+  struct Plugin *plugin;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Loading attribute plugin `%s'\n",
+              library_name);
+  plugin = GNUNET_new (struct Plugin);
+  plugin->api = api;
+  plugin->library_name = GNUNET_strdup (library_name);
+  GNUNET_array_append (attr_plugins, num_plugins, plugin);
+}
+
+/**
+ * Load plugins
+ */
+static void
+init()
+{
+  if (GNUNET_YES == initialized)
+    return;
+  initialized = GNUNET_YES;
+  GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_attribute_", NULL,
+                          &add_plugin, NULL);
+}
+
+/**
+ * Convert a type name to the corresponding number
+ *
+ * @param typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+uint32_t
+GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (const char *typename)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  uint32_t ret;
+  
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = attr_plugins[i];
+    if (UINT32_MAX != (ret = plugin->api->typename_to_number (plugin->api->cls,
+                                                              typename)))
+      return ret;
+  }
+  return UINT32_MAX;
+}
+
+/**
+ * Convert a type number to the corresponding type string
+ *
+ * @param type number of a type
+ * @return corresponding typestring, NULL on error
+ */
+const char*
+GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (uint32_t type)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  const char *ret;
+
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = attr_plugins[i];
+    if (NULL != (ret = plugin->api->number_to_typename (plugin->api->cls,
+                                                        type)))
+      return ret;
+  }
+  return NULL;
+}
+
+/**
+ * Convert human-readable version of a 'claim' of an attribute to the binary
+ * representation
+ *
+ * @param type type of the claim
+ * @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
+ */
+int
+GNUNET_RECLAIM_ATTRIBUTE_string_to_value (uint32_t type,
+                                           const char *s,
+                                           void **data,
+                                           size_t *data_size)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = attr_plugins[i];
+    if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
+                                                   type,
+                                                   s,
+                                                   data,
+                                                   data_size))
+      return GNUNET_OK;
+  }
+  return GNUNET_SYSERR;
+}
+
+/**
+ * Convert the 'claim' of an attribute to a string
+ *
+ * @param type the type of attribute
+ * @param data claim in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the claim
+ */
+char *
+GNUNET_RECLAIM_ATTRIBUTE_value_to_string (uint32_t type,
+                                           const void* data,
+                                           size_t data_size)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  char *ret;
+
+  init();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = attr_plugins[i];
+    if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
+                                                     type,
+                                                     data,
+                                                     data_size)))
+      return ret;
+  }
+  return NULL;
+}
+
+/**
+ * Create a new attribute.
+ *
+ * @param attr_name the attribute name
+ * @param type the attribute type
+ * @param data the attribute value
+ * @param data_size the attribute value size
+ * @return the new attribute
+ */
+struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
+GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char* attr_name,
+               uint32_t type,
+               const void* data,
+               size_t data_size)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
+  char *write_ptr;
+
+  attr = GNUNET_malloc (sizeof (struct GNUNET_RECLAIM_ATTRIBUTE_Claim) +
+                        strlen (attr_name) + 1 +
+                        data_size);
+  attr->type = type;
+  attr->data_size = data_size;
+  attr->version = 0;
+  write_ptr = (char*)&attr[1];
+  GNUNET_memcpy (write_ptr,
+                 attr_name,
+                 strlen (attr_name) + 1);
+  attr->name = write_ptr;
+  write_ptr += strlen (attr->name) + 1;
+  GNUNET_memcpy (write_ptr,
+                 data,
+                 data_size);
+  attr->data = write_ptr;
+  return attr;
+}
+
+/**
+ * Add a new claim list entry.
+ *
+ * @param claim_list the attribute name
+ * @param attr_name the attribute name
+ * @param type the attribute type
+ * @param data the attribute value
+ * @param data_size the attribute value size
+ * @return
+ */
+void
+GNUNET_RECLAIM_ATTRIBUTE_list_add (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *claim_list,
+                                   const char* attr_name,
+                                   uint32_t type,
+                                   const void* data,
+                                   size_t data_size)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+  le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name,
+                                              type,
+                                              data,
+                                              data_size);
+  GNUNET_CONTAINER_DLL_insert (claim_list->list_head,
+                              claim_list->list_tail,
+                              le);
+}
+
+size_t
+GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  size_t len = 0;
+  for (le = attrs->list_head; NULL != le; le = le->next)
+    len += GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
+  return len; 
+}
+
+size_t
+GNUNET_RECLAIM_ATTRIBUTE_list_serialize (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+                          char *result)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  size_t len;
+  size_t total_len;
+  char* write_ptr;
+
+  write_ptr = result;
+  total_len = 0;
+  for (le = attrs->list_head; NULL != le; le = le->next)
+  {
+    len = GNUNET_RECLAIM_ATTRIBUTE_serialize (le->claim,
+                               write_ptr);
+    total_len += len;
+    write_ptr += len;
+  }
+  return total_len;
+}
+
+struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
+GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (const char* data,
+                       size_t data_size)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  size_t attr_len;
+  const char* read_ptr;
+
+  if (data_size < sizeof (struct Attribute))
+    return NULL;
+  
+  attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
+  read_ptr = data;
+  while (((data + data_size) - read_ptr) >= sizeof (struct Attribute))
+  {
+
+    le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+    le->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize (read_ptr,
+                                           data_size - (read_ptr - data));
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Deserialized attribute %s\n", le->claim->name);
+    GNUNET_CONTAINER_DLL_insert (attrs->list_head,
+                                 attrs->list_tail,
+                                 le);
+    attr_len = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
+    read_ptr += attr_len;
+  }
+  return attrs;
+}
+
+struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList*
+GNUNET_RECLAIM_ATTRIBUTE_list_dup (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *result_le;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *result;
+
+  result = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
+  for (le = attrs->list_head; NULL != le; le = le->next)
+  {
+    result_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+    result_le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (le->claim->name,
+                                                     le->claim->type,
+                                                     le->claim->data,
+                                                     le->claim->data_size);
+    GNUNET_CONTAINER_DLL_insert (result->list_head,
+                                 result->list_tail,
+                                 result_le);
+  }
+  return result;
+}
+
+
+void
+GNUNET_RECLAIM_ATTRIBUTE_list_destroy (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *tmp_le;
+
+  for (le = attrs->list_head; NULL != le;)
+  {
+    GNUNET_free (le->claim);
+    tmp_le = le;
+    le = le->next;
+    GNUNET_free (tmp_le);
+  }
+  GNUNET_free (attrs);
+
+}
+
+size_t
+GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+{
+  return sizeof (struct Attribute) 
+    + strlen (attr->name)
+    + attr->data_size;
+}
+
+size_t
+GNUNET_RECLAIM_ATTRIBUTE_serialize (const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
+                     char *result)
+{
+  size_t data_len_ser;
+  size_t name_len;
+  struct Attribute *attr_ser;
+  char* write_ptr;
+
+  attr_ser = (struct Attribute*)result;
+  attr_ser->attribute_type = htons (attr->type);
+  attr_ser->attribute_version = htonl (attr->version);
+  name_len = strlen (attr->name);
+  attr_ser->name_len = htons (name_len);
+  write_ptr = (char*)&attr_ser[1];
+  GNUNET_memcpy (write_ptr, attr->name, name_len);
+  write_ptr += name_len;
+  //TODO plugin-ize
+  //data_len_ser = plugin->serialize_attribute_value (attr,
+  //                                                  &attr_ser[1]);
+  data_len_ser = attr->data_size;
+  GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
+  attr_ser->data_size = htons (data_len_ser);
+
+  return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
+}
+
+struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
+GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char* data,
+                       size_t data_size)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
+  struct Attribute *attr_ser;
+  size_t data_len;
+  size_t name_len;
+  char* write_ptr;
+
+  if (data_size < sizeof (struct Attribute))
+    return NULL;
+
+  attr_ser = (struct Attribute*)data;
+  data_len = ntohs (attr_ser->data_size);
+  name_len = ntohs (attr_ser->name_len);
+  attr = GNUNET_malloc (sizeof (struct GNUNET_RECLAIM_ATTRIBUTE_Claim)
+                        + data_len + name_len + 1);
+  attr->type = ntohs (attr_ser->attribute_type);
+  attr->version = ntohl (attr_ser->attribute_version);
+  attr->data_size = ntohs (attr_ser->data_size);
+
+  write_ptr =  (char*)&attr[1];
+  GNUNET_memcpy (write_ptr,
+                 &attr_ser[1],
+                 name_len);
+  write_ptr[name_len] = '\0';
+  attr->name = write_ptr;
+
+  write_ptr += name_len + 1;
+  GNUNET_memcpy (write_ptr,
+                 (char*)&attr_ser[1] + name_len,
+                 attr->data_size);
+  attr->data = write_ptr;
+  return attr;
+
+}
+
+/* end of reclaim_attribute.c */
diff --git a/src/reclaim-attribute/reclaim_attribute.h b/src/reclaim-attribute/reclaim_attribute.h
new file mode 100644 (file)
index 0000000..746d329
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+  
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @file reclaim-attribute/reclaim_attribute.h
+ * @brief GNUnet reclaim identity attributes
+ *
+ */
+#ifndef RECLAIM_ATTRIBUTE_H
+#define RECLAIM_ATTRIBUTE_H
+
+#include "gnunet_reclaim_service.h"
+
+struct Attribute
+{
+  /**
+   * Attribute type
+   */
+  uint32_t attribute_type;
+
+  /**
+   * Attribute version
+   */
+  uint32_t attribute_version;
+
+  /**
+   * Name length
+   */
+  uint32_t name_len;
+  
+  /**
+   * Data size
+   */
+  uint32_t data_size;
+
+  //followed by data_size Attribute value data
+};
+
+#endif
diff --git a/src/reclaim/.gitignore b/src/reclaim/.gitignore
new file mode 100644 (file)
index 0000000..ef77fcc
--- /dev/null
@@ -0,0 +1,2 @@
+gnunet-service-identity-provider
+gnunet-identity-token
diff --git a/src/reclaim/Makefile.am b/src/reclaim/Makefile.am
new file mode 100644 (file)
index 0000000..c13c687
--- /dev/null
@@ -0,0 +1,140 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+ plugindir = $(libdir)/gnunet
+
+if MINGW
+ WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+endif
+
+if USE_COVERAGE
+  AM_CFLAGS = --coverage -O0
+  XLIB = -lgcov
+endif
+
+if HAVE_SQLITE
+SQLITE_PLUGIN = libgnunet_plugin_reclaim_sqlite.la
+endif
+
+EXTRA_DIST = \
+  test_reclaim_defaults.conf \
+       test_reclaim.conf \
+       $(check_SCRIPTS)
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+pkgcfg_DATA = \
+  reclaim.conf
+
+lib_LTLIBRARIES = \
+  libgnunetidentityprovider.la
+plugin_LTLIBRARIES = \
+       libgnunet_plugin_rest_reclaim.la \
+       libgnunet_plugin_rest_openid_connect.la \
+  libgnunet_plugin_gnsrecord_reclaim.la \
+       $(SQLITE_PLUGIN)
+
+bin_PROGRAMS = \
+ gnunet-reclaim
+
+libexec_PROGRAMS = \
+ gnunet-service-reclaim
+
+libgnunet_plugin_gnsrecord_reclaim_la_SOURCES = \
+  plugin_gnsrecord_reclaim.c
+libgnunet_plugin_gnsrecord_reclaim_la_LIBADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(LTLIBINTL)
+libgnunet_plugin_gnsrecord_reclaim_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+libgnunet_plugin_reclaim_sqlite_la_SOURCES = \
+  plugin_reclaim_sqlite.c
+libgnunet_plugin_reclaim_sqlite_la_LIBADD = \
+  libgnunetidentityprovider.la  \
+  $(top_builddir)/src/sq/libgnunetsq.la \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \
+  $(LTLIBINTL)
+libgnunet_plugin_reclaim_sqlite_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
+
+gnunet_service_reclaim_SOURCES = \
+ gnunet-service-reclaim.c
+gnunet_service_reclaim_LDADD = \
+ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/identity/libgnunetidentity.la \
+ $(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(top_builddir)/src/abe/libgnunetabe.la \
+ $(top_builddir)/src/credential/libgnunetcredential.la \
+ $(top_builddir)/src/reclaim-attribute/libgnunetreclaimattribute.la \
+ libgnunetidentityprovider.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(GN_LIBINTL)
+
+libgnunetidentityprovider_la_SOURCES = \
+ reclaim_api.c \
+ reclaim.h
+libgnunetidentityprovider_la_LIBADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+       $(GN_LIBINTL) $(XLIB)
+libgnunetidentityprovider_la_LDFLAGS = \
+       $(GN_LIB_LDFLAGS)  $(WINFLAGS) \
+       -version-info 0:0:0
+
+libgnunet_plugin_rest_reclaim_la_SOURCES = \
+  plugin_rest_reclaim.c \
+       jwt.c
+libgnunet_plugin_rest_reclaim_la_LIBADD = \
+       $(top_builddir)/src/identity/libgnunetidentity.la \
+       libgnunetidentityprovider.la \
+       $(top_builddir)/src/rest/libgnunetrest.la \
+       $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
+       $(top_builddir)/src/reclaim-attribute/libgnunetreclaimattribute.la \
+       $(top_builddir)/src/namestore/libgnunetnamestore.la \
+  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+  $(LTLIBINTL) -ljansson -lmicrohttpd
+libgnunet_plugin_rest_reclaim_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+libgnunet_plugin_rest_openid_connect_la_SOURCES = \
+  plugin_rest_openid_connect.c \
+       jwt.c
+libgnunet_plugin_rest_openid_connect_la_LIBADD = \
+       $(top_builddir)/src/identity/libgnunetidentity.la \
+       libgnunetidentityprovider.la \
+       $(top_builddir)/src/rest/libgnunetrest.la \
+       $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
+       $(top_builddir)/src/reclaim-attribute/libgnunetreclaimattribute.la \
+       $(top_builddir)/src/namestore/libgnunetnamestore.la \
+  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+  $(LTLIBINTL) -ljansson -lmicrohttpd
+libgnunet_plugin_rest_openid_connect_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+gnunet_reclaim_SOURCES = \
+ gnunet-reclaim.c
+gnunet_reclaim_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+       $(top_builddir)/src/namestore/libgnunetnamestore.la \
+       libgnunetidentityprovider.la \
+       $(top_builddir)/src/identity/libgnunetidentity.la \
+       $(top_builddir)/src/reclaim-attribute/libgnunetreclaimattribute.la \
+  $(GN_LIBINTL)
+
+check_SCRIPTS = \
+       test_reclaim_attribute.sh \
+       test_reclaim_issue.sh \
+       test_reclaim_consume.sh \
+  test_reclaim_revoke.sh
+
+if ENABLE_TEST_RUN
+ AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
+ TESTS = $(check_SCRIPTS)
+endif
diff --git a/src/reclaim/gnunet-reclaim.c b/src/reclaim/gnunet-reclaim.c
new file mode 100644 (file)
index 0000000..9947eac
--- /dev/null
@@ -0,0 +1,517 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+  
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @file src/reclaim/gnunet-reclaim.c
+ * @brief Identity Provider utility
+ *
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_reclaim_service.h"
+#include "gnunet_identity_service.h"
+#include "gnunet_signatures.h"
+
+/**
+ * return value
+ */
+static int ret;
+
+/**
+ * List attribute flag
+ */
+static int list;
+
+/**
+ * Relying party
+ */
+static char* rp;
+
+/**
+ * The attribute
+ */
+static char* attr_name;
+
+/**
+ * Attribute value
+ */
+static char* attr_value;
+
+/**
+ * Attributes to issue
+ */
+static char* issue_attrs;
+
+/**
+ * Ticket to consume
+ */
+static char* consume_ticket;
+
+/**
+ * Attribute type
+ */
+static char* type_str;
+
+/**
+ * Ticket to revoke
+ */
+static char* revoke_ticket;
+
+/**
+ * Ego name
+ */
+static char* ego_name;
+
+/**
+ * Identity handle
+ */
+static struct GNUNET_IDENTITY_Handle *identity_handle;
+
+/**
+ * reclaim handle
+ */
+static struct GNUNET_RECLAIM_Handle *reclaim_handle;
+
+/**
+ * reclaim operation
+ */
+static struct GNUNET_RECLAIM_Operation *reclaim_op;
+
+/**
+ * Attribute iterator
+ */
+static struct GNUNET_RECLAIM_AttributeIterator *attr_iterator;
+
+/**
+ * Master ABE key
+ */
+static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
+
+/**
+ * ego private key
+ */
+static const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey;
+
+/**
+ * rp public key
+ */
+static struct GNUNET_CRYPTO_EcdsaPublicKey rp_key;
+
+/**
+ * Ticket to consume
+ */
+static struct GNUNET_RECLAIM_Ticket ticket;
+
+/**
+ * Attribute list
+ */
+static struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list;
+
+/**
+ * Attribute expiration interval
+ */
+static struct GNUNET_TIME_Relative exp_interval;
+
+/**
+ * Timeout task
+ */
+static struct GNUNET_SCHEDULER_Task *timeout;
+
+static void
+do_cleanup(void *cls)
+{
+  if (NULL != timeout)
+    GNUNET_SCHEDULER_cancel (timeout);
+  if (NULL != reclaim_op)
+    GNUNET_RECLAIM_cancel (reclaim_op);
+  if (NULL != attr_iterator)
+    GNUNET_RECLAIM_get_attributes_stop (attr_iterator);
+  if (NULL != reclaim_handle)
+    GNUNET_RECLAIM_disconnect (reclaim_handle);
+  if (NULL != identity_handle)
+    GNUNET_IDENTITY_disconnect (identity_handle);
+  if (NULL != abe_key)
+    GNUNET_free (abe_key);
+  if (NULL != attr_list)
+    GNUNET_free (attr_list);
+}
+
+static void
+ticket_issue_cb (void* cls,
+                 const struct GNUNET_RECLAIM_Ticket *ticket)
+{
+  char* ticket_str;
+  reclaim_op = NULL;
+  if (NULL != ticket) {
+    ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
+                                                      sizeof (struct GNUNET_RECLAIM_Ticket));
+    printf("%s\n",
+           ticket_str);
+    GNUNET_free (ticket_str);
+  }
+  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+}
+
+static void
+store_attr_cont (void *cls,
+                 int32_t success,
+                 const char*emsg)
+{
+  reclaim_op = NULL;
+  if (GNUNET_SYSERR == success) {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "%s\n", emsg);
+  }
+  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+}
+
+static void
+process_attrs (void *cls,
+         const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+         const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+{
+  char *value_str;
+  if (NULL == identity)
+  {
+    reclaim_op = NULL;
+    GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+    return;
+  }
+  if (NULL == attr)
+  {
+    ret = 1;
+    return;
+  }
+  value_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
+                                                        attr->data,
+                                                        attr->data_size);
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+              "%s: %s\n", attr->name, value_str);
+}
+
+
+static void
+iter_error (void *cls)
+{
+  attr_iterator = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Failed to iterate over attributes\n");
+  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+}
+
+static void
+timeout_task (void *cls)
+{
+  timeout = NULL;
+  ret = 1;
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+              "Timeout\n");
+  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+}
+
+static void
+process_rvk (void *cls, int success, const char* msg)
+{
+  reclaim_op = NULL;
+  if (GNUNET_OK != success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                "Revocation failed.\n");
+    ret = 1;
+  }
+  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+}
+
+static void
+iter_finished (void *cls)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
+  char *data;
+  size_t data_size;
+  int type;
+
+  attr_iterator = NULL;
+  if (list)
+  {
+    GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+    return;
+  }
+
+  if (issue_attrs)
+  {
+    reclaim_op = GNUNET_RECLAIM_ticket_issue (reclaim_handle,
+                                              pkey,
+                                              &rp_key,
+                                              attr_list,
+                                              &ticket_issue_cb,
+                                              NULL);
+    return;
+  }
+  if (consume_ticket)
+  {
+    reclaim_op = GNUNET_RECLAIM_ticket_consume (reclaim_handle,
+                                                pkey,
+                                                &ticket,
+                                                &process_attrs,
+                                                NULL);
+    timeout = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10),
+                                            &timeout_task,
+                                            NULL);
+    return;
+  }
+  if (revoke_ticket)
+  {
+    reclaim_op = GNUNET_RECLAIM_ticket_revoke (reclaim_handle,
+                                               pkey,
+                                               &ticket,
+                                               &process_rvk,
+                                               NULL);
+    return;
+  }
+  if (attr_name)
+  {
+    if (NULL == type_str)
+      type = GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING;
+    else
+      type = GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (type_str);
+
+    GNUNET_assert (GNUNET_SYSERR != GNUNET_RECLAIM_ATTRIBUTE_string_to_value (type,
+                                                                              attr_value,
+                                                                              (void**)&data,
+                                                                              &data_size));
+    claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name,
+                                                 type,
+                                                 data,
+                                                 data_size);
+    reclaim_op = GNUNET_RECLAIM_attribute_store (reclaim_handle,
+                                                 pkey,
+                                                 claim,
+                                                 &exp_interval,
+                                                 &store_attr_cont,
+                                                 NULL);
+    return;
+  }
+  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+}
+
+static void
+iter_cb (void *cls,
+         const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+         const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  char *attrs_tmp;
+  char *attr_str;
+
+  if (issue_attrs)
+  {
+    attrs_tmp = GNUNET_strdup (issue_attrs);
+    attr_str = strtok (attrs_tmp, ",");
+    while (NULL != attr_str) {
+      if (0 != strcmp (attr_str, attr->name)) {
+        attr_str = strtok (NULL, ",");
+        continue;
+      }
+      le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+      le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name,
+                                                      attr->type,
+                                                      attr->data,
+                                                      attr->data_size);
+      GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
+                                   attr_list->list_tail,
+                                   le);
+      break;
+    }
+    GNUNET_free (attrs_tmp);
+  } else if (list) {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                "%s: %s\n", attr->name, (char*)attr->data);
+  }
+  GNUNET_RECLAIM_get_attributes_next (attr_iterator);
+}
+
+static void
+ego_iter_finished (void *cls)
+{
+  if (NULL == pkey)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                "Ego %s not found\n", ego_name);
+    return;
+  }
+
+  if (NULL != rp)
+    GNUNET_CRYPTO_ecdsa_public_key_from_string (rp,
+                                                strlen (rp),
+                                                &rp_key);
+  if (NULL != consume_ticket)
+    GNUNET_STRINGS_string_to_data (consume_ticket,
+                                   strlen (consume_ticket),
+                                   &ticket,
+                                   sizeof (struct GNUNET_RECLAIM_Ticket));
+  if (NULL != revoke_ticket)
+    GNUNET_STRINGS_string_to_data (revoke_ticket,
+                                   strlen (revoke_ticket),
+                                   &ticket,
+                                   sizeof (struct GNUNET_RECLAIM_Ticket));
+
+
+  attr_list = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
+
+  attr_iterator = GNUNET_RECLAIM_get_attributes_start (reclaim_handle,
+                                                       pkey,
+                                                       &iter_error,
+                                                       NULL,
+                                                       &iter_cb,
+                                                       NULL,
+                                                       &iter_finished,
+                                                       NULL);
+
+
+}
+
+static int init = GNUNET_YES;
+
+static void
+ego_cb (void *cls,
+        struct GNUNET_IDENTITY_Ego *ego,
+        void **ctx,
+        const char *name)
+{
+  if (NULL == name) {
+    if (GNUNET_YES == init) {
+      init = GNUNET_NO;
+      GNUNET_SCHEDULER_add_now (&ego_iter_finished, NULL);
+    }
+    return;
+  }
+  if (0 != strcmp (name, ego_name))
+    return;
+  pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
+}
+
+
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  ret = 0;
+  if (NULL == ego_name)
+  {
+    ret = 1;
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                _("Ego is required\n"));
+    return;
+  }
+
+  if ( (NULL == attr_value) && (NULL != attr_name) )
+  {
+    ret = 1;
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                _("Attribute value missing!\n"));
+    return;
+  }
+
+  if ( (NULL == rp) && (NULL != issue_attrs) )
+  {
+    ret = 1;
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                _("Requesting party key is required!\n"));
+    return;
+  }
+
+  reclaim_handle = GNUNET_RECLAIM_connect (c);
+  //Get Ego
+  identity_handle = GNUNET_IDENTITY_connect (c,
+                                             &ego_cb,
+                                             NULL);
+
+
+}
+
+
+int
+main(int argc, char *const argv[])
+{
+  exp_interval = GNUNET_TIME_UNIT_HOURS;
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+
+    GNUNET_GETOPT_option_string ('a',
+                                 "add",
+                                 NULL,
+                                 gettext_noop ("Add attribute"),
+                                 &attr_name),
+
+    GNUNET_GETOPT_option_string ('V',
+                                 "value",
+                                 NULL,
+                                 gettext_noop ("Attribute value"),
+                                 &attr_value),
+    GNUNET_GETOPT_option_string ('e',
+                                 "ego",
+                                 NULL,
+                                 gettext_noop ("Ego"),
+                                 &ego_name),
+    GNUNET_GETOPT_option_string ('r',
+                                 "rp",
+                                 NULL,
+                                 gettext_noop ("Audience (relying party)"),
+                                 &rp),
+    GNUNET_GETOPT_option_flag ('D',
+                               "dump",
+                               gettext_noop ("List attributes for Ego"),
+                               &list),
+    GNUNET_GETOPT_option_string ('i',
+                                 "issue",
+                                 NULL,
+                                 gettext_noop ("Issue a ticket"),
+                                 &issue_attrs),
+    GNUNET_GETOPT_option_string ('C',
+                                 "consume",
+                                 NULL,
+                                 gettext_noop ("Consume a ticket"),
+                                 &consume_ticket),
+    GNUNET_GETOPT_option_string ('R',
+                                 "revoke",
+                                 NULL,
+                                 gettext_noop ("Revoke a ticket"),
+                                 &revoke_ticket),
+    GNUNET_GETOPT_option_string ('t',
+                                 "type",
+                                 NULL,
+                                 gettext_noop ("Type of attribute"),
+                                 &type_str),
+    GNUNET_GETOPT_option_relative_time ('E',
+                                        "expiration",
+                                        NULL,
+                                        gettext_noop ("Expiration interval of the attribute"),
+                                        &exp_interval),
+
+    GNUNET_GETOPT_OPTION_END
+  };
+  if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "ct",
+                                       "ct", options,
+                                       &run, NULL))
+    return 1;
+  else
+    return ret;
+}
diff --git a/src/reclaim/gnunet-service-reclaim.c b/src/reclaim/gnunet-service-reclaim.c
new file mode 100644 (file)
index 0000000..bf8780a
--- /dev/null
@@ -0,0 +1,2786 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+  
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @file src/reclaim/gnunet-service-reclaim.c
+ * @brief reclaim Service
+ *
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_protocols.h"
+#include "gnunet_identity_service.h"
+#include "gnunet_gnsrecord_lib.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_abe_lib.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_gns_service.h"
+#include "gnunet_reclaim_plugin.h"
+#include "gnunet_reclaim_attribute_lib.h"
+#include "gnunet_signatures.h"
+#include "reclaim.h"
+
+/**
+ * First pass state
+ */
+#define STATE_INIT 0
+
+/**
+ * Normal operation state
+ */
+#define STATE_POST_INIT 1
+
+/**
+ * Minimum interval between updates
+ */
+#define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
+
+/**
+ * Standard token expiration time
+ */
+#define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
+
+/**
+ * Identity handle
+ */
+static struct GNUNET_IDENTITY_Handle *identity_handle;
+
+/**
+ * Database handle
+ */
+static struct GNUNET_RECLAIM_PluginFunctions *TKT_database;
+
+/**
+ * Name of DB plugin
+ */
+static char *db_lib_name;
+
+/**
+ * Token expiration interval
+ */
+static struct GNUNET_TIME_Relative token_expiration_interval;
+
+/**
+ * Namestore handle
+ */
+static struct GNUNET_NAMESTORE_Handle *ns_handle;
+
+/**
+ * GNS handle
+ */
+static struct GNUNET_GNS_Handle *gns_handle;
+
+/**
+ * Credential handle
+ */
+static struct GNUNET_CREDENTIAL_Handle *credential_handle;
+
+/**
+ * Namestore qe
+ */
+static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+/**
+ * Namestore iterator
+ */
+static struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+
+/**
+ * Timeout task
+ */
+static struct GNUNET_SCHEDULER_Task *timeout_task;
+
+/**
+ * Update task
+ */
+static struct GNUNET_SCHEDULER_Task *update_task;
+
+
+/**
+ * Currently processed token
+ */
+static struct IdentityToken *token;
+
+/**
+ * Label for currently processed token
+ */
+static char* label;
+
+/**
+ * Scopes for processed token
+ */
+static char* scopes;
+
+/**
+ * Handle to the statistics service.
+ */
+static struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Our configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * An idp client
+ */
+struct IdpClient;
+
+/**
+ * A ticket iteration operation.
+ */
+struct TicketIteration
+{
+  /**
+   * DLL
+   */
+  struct TicketIteration *next;
+
+  /**
+   * DLL
+   */
+  struct TicketIteration *prev;
+
+  /**
+   * Client which intiated this zone iteration
+   */
+  struct IdpClient *client;
+
+  /**
+   * Key of the identity we are iterating over.
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
+
+  /**
+   * Identity is audience
+   */
+  uint32_t is_audience;
+
+  /**
+   * The operation id fot the iteration in the response for the client
+   */
+  uint32_t r_id;
+
+  /**
+   * Offset of the iteration used to address next result of the 
+   * iteration in the store
+   *
+   * Initialy set to 0 in handle_iteration_start
+   * Incremented with by every call to handle_iteration_next
+   */
+  uint32_t offset;
+
+};
+
+
+
+/**
+ * Callback after an ABE bootstrap
+ *
+ * @param cls closure
+ * @param abe_key the ABE key that exists or was created
+ */
+typedef void
+(*AbeBootstrapResult) (void *cls,
+                       struct GNUNET_ABE_AbeMasterKey *abe_key);
+
+
+struct AbeBootstrapHandle
+{
+  /**
+   * Function to call when finished
+   */
+  AbeBootstrapResult proc;
+
+  /**
+   * Callback closure
+   */
+  char *proc_cls;
+
+  /**
+   * Key of the zone we are iterating over.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * Namestore Queue Entry
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+  /**
+   * The issuer egos ABE master key
+   */
+  struct GNUNET_ABE_AbeMasterKey *abe_key;
+};
+
+/**
+ * An attribute iteration operation.
+ */
+struct AttributeIterator
+{
+  /**
+   * Next element in the DLL
+   */
+  struct AttributeIterator *next;
+
+  /**
+   * Previous element in the DLL
+   */
+  struct AttributeIterator *prev;
+
+  /**
+   * IDP client which intiated this zone iteration
+   */
+  struct IdpClient *client;
+
+  /**
+   * Key of the zone we are iterating over.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * The issuer egos ABE master key
+   */
+  struct GNUNET_ABE_AbeMasterKey *abe_key;
+
+  /**
+   * Namestore iterator
+   */
+  struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+
+  /**
+   * The operation id fot the zone iteration in the response for the client
+   */
+  uint32_t request_id;
+
+};
+
+
+
+/**
+ * An idp client
+ */
+struct IdpClient
+{
+
+  /**
+   * The client
+   */
+  struct GNUNET_SERVICE_Client *client;
+
+  /**
+   * Message queue for transmission to @e client
+   */
+  struct GNUNET_MQ_Handle *mq;
+  
+  /**
+   * Head of the DLL of
+   * Attribute iteration operations in 
+   * progress initiated by this client
+   */
+  struct AttributeIterator *attr_iter_head;
+
+  /**
+   * Tail of the DLL of
+   * Attribute iteration operations 
+   * in progress initiated by this client
+   */
+  struct AttributeIterator *attr_iter_tail;
+
+  /**
+   * Head of DLL of ticket iteration ops
+   */
+  struct TicketIteration *ticket_iter_head;
+
+  /**
+   * Tail of DLL of ticket iteration ops
+   */
+  struct TicketIteration *ticket_iter_tail;
+
+  /**
+   * Head of DLL of ticket revocation ops
+   */
+  struct TicketRevocationHandle *revoke_op_head;
+
+  /**
+   * Tail of DLL of ticket revocation ops
+   */
+  struct TicketRevocationHandle *revoke_op_tail;
+
+  /**
+   * Head of DLL of ticket issue ops
+   */
+  struct TicketIssueHandle *issue_op_head;
+
+  /**
+   * Tail of DLL of ticket issue ops
+   */
+  struct TicketIssueHandle *issue_op_tail;
+
+  /**
+   * Head of DLL of ticket consume ops
+   */
+  struct ConsumeTicketHandle *consume_op_head;
+
+  /**
+   * Tail of DLL of ticket consume ops
+   */
+  struct ConsumeTicketHandle *consume_op_tail;
+
+  /**
+   * Head of DLL of attribute store ops
+   */
+  struct AttributeStoreHandle *store_op_head;
+
+  /**
+   * Tail of DLL of attribute store ops
+   */
+  struct AttributeStoreHandle *store_op_tail;
+
+};
+
+struct AttributeStoreHandle
+{
+  /**
+   * DLL
+   */
+  struct AttributeStoreHandle *next;
+
+  /**
+   * DLL
+   */
+  struct AttributeStoreHandle *prev;
+
+  /**
+   * Client connection
+   */
+  struct IdpClient *client;
+
+  /**
+   * Identity
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * Identity pubkey
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
+
+  /**
+   * The issuer egos ABE master key
+   */
+  struct GNUNET_ABE_AbeMasterKey *abe_key;
+
+  /**
+   * QueueEntry
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+  /**
+   * The attribute to store
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
+
+  /**
+   * The attribute expiration interval
+   */
+  struct GNUNET_TIME_Relative exp;
+
+  /**
+   * request id
+   */
+  uint32_t r_id;
+};
+
+
+/* Prototype */
+struct ParallelLookup;
+
+struct ConsumeTicketHandle
+{
+  /**
+   * DLL
+   */
+  struct ConsumeTicketHandle *next;
+
+  /**
+   * DLL
+   */
+  struct ConsumeTicketHandle *prev;
+
+  /**
+   * Client connection
+   */
+  struct IdpClient *client;
+
+  /**
+   * Ticket
+   */
+  struct GNUNET_RECLAIM_Ticket ticket;
+
+  /**
+   * LookupRequest
+   */
+  struct GNUNET_GNS_LookupRequest *lookup_request;
+
+  /**
+   * Audience Key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * Audience Key
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
+
+  /**
+   * Lookup DLL
+   */
+  struct ParallelLookup *parallel_lookups_head;
+
+  /**
+   * Lookup DLL
+   */
+  struct ParallelLookup *parallel_lookups_tail;
+  
+  /**
+   * Kill task
+   */
+  struct GNUNET_SCHEDULER_Task *kill_task;
+
+  /**
+   * The ABE key
+   */
+  struct GNUNET_ABE_AbeKey *key;
+
+  /**
+   * Attributes
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
+  
+  /**
+   * Lookup time
+   */
+  struct GNUNET_TIME_Absolute lookup_start_time;
+  /**
+   * request id
+   */
+  uint32_t r_id;
+};
+
+/**
+ * Handle for a parallel GNS lookup job
+ */
+struct ParallelLookup
+{
+  /* DLL */
+  struct ParallelLookup *next;
+
+  /* DLL */
+  struct ParallelLookup *prev;
+
+  /* The GNS request */
+  struct GNUNET_GNS_LookupRequest *lookup_request;
+
+  /* The handle the return to */
+  struct ConsumeTicketHandle *handle;
+
+  /**
+   * Lookup time
+   */
+  struct GNUNET_TIME_Absolute lookup_start_time;
+
+  /* The label to look up */
+  char *label;
+};
+
+/**
+ * Ticket revocation request handle
+ */
+struct TicketRevocationHandle
+{
+  /**
+   * DLL
+   */
+  struct TicketRevocationHandle *prev;
+
+  /**
+   * DLL
+   */
+  struct TicketRevocationHandle *next;
+
+  /**
+   * Client connection
+   */
+  struct IdpClient *client;
+
+  /**
+   * Attributes to reissue
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
+
+  /**
+   * Attributes to revoke
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *rvk_attrs;
+
+  /**
+   * Issuer Key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * Ticket to issue
+   */
+  struct GNUNET_RECLAIM_Ticket ticket;
+
+  /**
+   * QueueEntry
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+  /**
+   * Namestore iterator
+   */
+  struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+
+  /**
+   * The ABE master key
+   */
+  struct GNUNET_ABE_AbeMasterKey *abe_key;
+
+  /**
+   * Offset
+   */
+  uint32_t offset;
+
+  /**
+   * request id
+   */
+  uint32_t r_id;
+};
+
+
+
+/**
+ * Ticket issue request handle
+ */
+struct TicketIssueHandle
+{
+  /**
+   * DLL
+   */
+  struct TicketIssueHandle *prev;
+
+  /**
+   * DLL
+   */
+  struct TicketIssueHandle *next;
+
+  /**
+   * Client connection
+   */
+  struct IdpClient *client;
+
+  /**
+   * Attributes to issue
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
+
+  /**
+   * Issuer Key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * Ticket to issue
+   */
+  struct GNUNET_RECLAIM_Ticket ticket;
+
+  /**
+   * QueueEntry
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+  /**
+   * request id
+   */
+  uint32_t r_id;
+};
+
+
+/**
+ * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
+ *
+ */
+struct EgoEntry
+{
+  /**
+   * DLL
+   */
+  struct EgoEntry *next;
+
+  /**
+   * DLL
+   */
+  struct EgoEntry *prev;
+
+  /**
+   * Ego handle
+   */
+  struct GNUNET_IDENTITY_Ego *ego;
+
+  /**
+   * Attribute map. Contains the attributes as json_t
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *attr_map;
+
+};
+
+/**
+ * Cleanup task
+ */
+static void
+cleanup()
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up\n");
+
+  if (NULL != stats)
+  {
+    GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
+    stats = NULL;
+  }
+  GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
+                                              TKT_database)); 
+  GNUNET_free (db_lib_name);
+  db_lib_name = NULL;
+  if (NULL != timeout_task)
+    GNUNET_SCHEDULER_cancel (timeout_task);
+  if (NULL != update_task)
+    GNUNET_SCHEDULER_cancel (update_task);
+  if (NULL != identity_handle)
+    GNUNET_IDENTITY_disconnect (identity_handle);
+  if (NULL != gns_handle)
+    GNUNET_GNS_disconnect (gns_handle);
+  if (NULL != credential_handle)
+    GNUNET_CREDENTIAL_disconnect (credential_handle);
+  if (NULL != ns_it)
+    GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
+  if (NULL != ns_qe)
+    GNUNET_NAMESTORE_cancel (ns_qe);
+  if (NULL != ns_handle)
+    GNUNET_NAMESTORE_disconnect (ns_handle);
+  GNUNET_free_non_null (token);
+  GNUNET_free_non_null (label);
+
+}
+
+/**
+ * Shutdown task
+ *
+ * @param cls NULL
+ */
+static void
+do_shutdown (void *cls)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Shutting down...\n");
+  cleanup();
+}
+
+/**
+ * Finished storing newly bootstrapped ABE key
+ */
+static void
+bootstrap_store_cont (void *cls,
+                      int32_t success,
+                      const char *emsg)
+{
+  struct AbeBootstrapHandle *abh = cls;
+  if (GNUNET_SYSERR == success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to bootstrap ABE master %s\n",
+                emsg);
+    abh->proc (abh->proc_cls, NULL);
+    GNUNET_free (abh->abe_key);
+    GNUNET_free (abh);
+    return;
+  }
+  abh->proc (abh->proc_cls, abh->abe_key);
+  GNUNET_free (abh);
+}
+
+/**
+ * Generates and stores a new ABE key
+ */
+static void
+bootstrap_store_task (void *cls)
+{
+  struct AbeBootstrapHandle *abh = cls;
+  struct GNUNET_GNSRECORD_Data rd[1];
+  char *key;
+
+  rd[0].data_size = GNUNET_ABE_cpabe_serialize_master_key (abh->abe_key,
+                                                              (void**)&key);
+  rd[0].data = key;
+  rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
+  rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
+  rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
+  abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                               &abh->identity,
+                                               "+",
+                                               1,
+                                               rd,
+                                               &bootstrap_store_cont,
+                                               abh);
+  GNUNET_free (key);
+}
+
+/**
+ * Error checking for ABE master
+ */
+static void
+bootstrap_abe_error (void *cls)
+{
+  struct AbeBootstrapHandle *abh = cls;
+  abh->proc (abh->proc_cls, NULL);
+  GNUNET_free (abh);
+}
+
+
+/**
+ * Handle ABE lookup in namestore
+ */
+static void
+bootstrap_abe_result (void *cls,
+                      const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                      const char *label,
+                      unsigned int rd_count,
+                      const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct AbeBootstrapHandle *abh = cls;
+  struct GNUNET_ABE_AbeMasterKey *abe_key;
+
+  for (uint32_t i=0;i<rd_count;i++) {
+    if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
+      continue;
+    abe_key = GNUNET_ABE_cpabe_deserialize_master_key (rd[i].data,
+                                                          rd[i].data_size);
+    abh->proc (abh->proc_cls, abe_key);
+    GNUNET_free (abh);
+    return;
+  }
+
+  //No ABE master found, bootstrapping...
+  abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
+  GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
+}
+
+/**
+ * Bootstrap ABE master if it does not yet exists.
+ * Will call the AbeBootstrapResult processor when done.
+ * will always recreate the ABE key of GNUNET_YES == recreate
+ */
+static void
+bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+               AbeBootstrapResult proc,
+               void* cls,
+               int recreate)
+{
+  struct AbeBootstrapHandle *abh;
+
+  abh = GNUNET_new (struct AbeBootstrapHandle);
+  abh->proc = proc;
+  abh->proc_cls = cls;
+  abh->identity = *identity;
+  if (GNUNET_YES == recreate)
+  {
+    abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
+    GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
+  } else {
+    abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
+                                                  identity,
+                                                  "+",
+                                                  &bootstrap_abe_error,
+                                                  abh,
+                                                  &bootstrap_abe_result,
+                                                  abh);
+  }
+}
+
+
+
+static int
+create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
+                         struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
+                         struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
+{
+  struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
+
+  GNUNET_CRYPTO_hash_to_enc (new_key_hash,
+                             &new_key_hash_str);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
+  static const char ctx_key[] = "gnuid-aes-ctx-key";
+  GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
+                     new_key_hash, sizeof (struct GNUNET_HashCode),
+                     ctx_key, strlen (ctx_key),
+                     NULL, 0);
+  static const char ctx_iv[] = "gnuid-aes-ctx-iv";
+  GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
+                     new_key_hash, sizeof (struct GNUNET_HashCode),
+                     ctx_iv, strlen (ctx_iv),
+                     NULL, 0);
+  return GNUNET_OK;
+}
+
+/**
+ * Cleanup ticket consume handle
+ * @param handle the handle to clean up
+ */
+static void
+cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
+{
+  if (NULL != handle->attrs)
+    GNUNET_RECLAIM_ATTRIBUTE_list_destroy (handle->attrs);
+  if (NULL != handle->ns_qe)
+    GNUNET_NAMESTORE_cancel (handle->ns_qe);
+  GNUNET_free (handle);
+}
+
+
+static void
+send_ticket_result (struct IdpClient *client,
+                    uint32_t r_id,
+                    const struct GNUNET_RECLAIM_Ticket *ticket,
+                    const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
+{
+  struct TicketResultMessage *irm;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_RECLAIM_Ticket *ticket_buf;
+
+  /* store ticket in DB */
+  if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
+                                               ticket,
+                                               attrs))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to store ticket after issue\n");
+    GNUNET_break (0);
+  }
+
+  env = GNUNET_MQ_msg_extra (irm,
+                             sizeof (struct GNUNET_RECLAIM_Ticket),
+                             GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
+  ticket_buf = (struct GNUNET_RECLAIM_Ticket *)&irm[1];
+  *ticket_buf = *ticket;
+  irm->id = htonl (r_id);
+  GNUNET_MQ_send (client->mq,
+                  env);
+}
+
+static void
+store_ticket_issue_cont (void *cls,
+                         int32_t success,
+                         const char *emsg)
+{
+  struct TicketIssueHandle *handle = cls;
+
+  handle->ns_qe = NULL;
+  GNUNET_CONTAINER_DLL_remove (handle->client->issue_op_head,
+                               handle->client->issue_op_tail,
+                               handle);
+  if (GNUNET_SYSERR == success)
+  {
+    cleanup_ticket_issue_handle (handle);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
+                "Unknown Error\n");
+    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+    return;
+  }
+  send_ticket_result (handle->client,
+                      handle->r_id,
+                      &handle->ticket,
+                      handle->attrs);
+  cleanup_ticket_issue_handle (handle);
+}
+
+
+
+int
+serialize_abe_keyinfo2 (const struct GNUNET_RECLAIM_Ticket *ticket,
+                        const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+                        const struct GNUNET_ABE_AbeKey *rp_key,
+                        struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
+                        char **result)
+{
+  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  char *enc_keyinfo;
+  char *serialized_key;
+  char *buf;
+  char *write_ptr;
+  char attrs_str_len;
+  ssize_t size;
+
+  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
+  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+  struct GNUNET_HashCode new_key_hash;
+  ssize_t enc_size;
+
+  size = GNUNET_ABE_cpabe_serialize_key (rp_key,
+                                         (void**)&serialized_key);
+  attrs_str_len = 0;
+  for (le = attrs->list_head; NULL != le; le = le->next) {
+    attrs_str_len += strlen (le->claim->name) + 1;
+  }
+  buf = GNUNET_malloc (attrs_str_len + size);
+  write_ptr = buf;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Writing attributes\n");
+  for (le = attrs->list_head; NULL != le; le = le->next) {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "%s\n", le->claim->name);
+
+
+    GNUNET_memcpy (write_ptr,
+                   le->claim->name,
+                   strlen (le->claim->name));
+    write_ptr[strlen (le->claim->name)] = ',';
+    write_ptr += strlen (le->claim->name) + 1;
+  }
+  write_ptr--;
+  write_ptr[0] = '\0'; //replace last , with a 0-terminator
+  write_ptr++;
+  GNUNET_memcpy (write_ptr,
+                 serialized_key,
+                 size);
+  GNUNET_free (serialized_key);
+  // ECDH keypair E = eG
+  *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
+  GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
+                                      &ecdh_pubkey);
+  enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
+  // Derived key K = H(eB)
+  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
+                                                        &ticket->audience,
+                                                        &new_key_hash));
+  create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
+  enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
+                                              size + attrs_str_len,
+                                              &skey, &iv,
+                                              enc_keyinfo);
+  *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
+                           enc_size);
+  GNUNET_memcpy (*result,
+                 &ecdh_pubkey,
+                 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+  GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
+                 enc_keyinfo,
+                 enc_size);
+  GNUNET_free (enc_keyinfo);
+  GNUNET_free (buf);
+  return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
+}
+
+
+
+static void
+issue_ticket_after_abe_bootstrap (void *cls,
+                                  struct GNUNET_ABE_AbeMasterKey *abe_key)
+{
+  struct TicketIssueHandle *ih = cls;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
+  struct GNUNET_GNSRECORD_Data code_record[1];
+  struct GNUNET_ABE_AbeKey *rp_key;
+  char *code_record_data;
+  char **attrs;
+  char *label;
+  char *policy;
+  int attrs_len;
+  uint32_t i;
+  size_t code_record_len;
+
+  //Create new ABE key for RP
+  attrs_len = 0;
+  for (le = ih->attrs->list_head; NULL != le; le = le->next)
+    attrs_len++;
+  attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
+  i = 0;
+  for (le = ih->attrs->list_head; NULL != le; le = le->next) {
+    GNUNET_asprintf (&policy, "%s_%lu",
+                     le->claim->name,
+                     le->claim->version);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Adding attribute to key: %s\n",
+                policy);
+    attrs[i] = policy;
+    i++;
+  }
+  attrs[i] = NULL;
+  rp_key = GNUNET_ABE_cpabe_create_key (abe_key,
+                                        attrs);
+
+  //TODO review this wireformat
+  code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
+                                            ih->attrs,
+                                            rp_key,
+                                            &ecdhe_privkey,
+                                            &code_record_data);
+  code_record[0].data = code_record_data;
+  code_record[0].data_size = code_record_len;
+  code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
+  code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
+  code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+
+  label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
+                                               sizeof (uint64_t));
+  //Publish record
+  ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                              &ih->identity,
+                                              label,
+                                              1,
+                                              code_record,
+                                              &store_ticket_issue_cont,
+                                              ih);
+  //for (; i > 0; i--)
+  //  GNUNET_free (attrs[i-1]);
+  GNUNET_free (ecdhe_privkey);
+  GNUNET_free (label);
+  GNUNET_free (attrs);
+  GNUNET_free (code_record_data);
+  GNUNET_ABE_cpabe_delete_key (rp_key,
+                               GNUNET_YES);
+  GNUNET_ABE_cpabe_delete_master_key (abe_key);
+}
+
+
+static int
+check_issue_ticket_message(void *cls,
+                           const struct IssueTicketMessage *im)
+{
+  uint16_t size;
+
+  size = ntohs (im->header.size);
+  if (size <= sizeof (struct IssueTicketMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+static void
+handle_issue_ticket_message (void *cls,
+                             const struct IssueTicketMessage *im)
+{
+  struct TicketIssueHandle *ih;
+  struct IdpClient *idp = cls;
+  size_t attrs_len;
+
+  ih = GNUNET_new (struct TicketIssueHandle);
+  attrs_len = ntohs (im->attr_len);
+  ih->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char*)&im[1], attrs_len);
+  ih->r_id = ntohl (im->id);
+  ih->client = idp;
+  ih->identity = im->identity;
+  GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
+                                      &ih->ticket.identity);
+  ih->ticket.audience = im->rp;
+  ih->ticket.rnd =
+    GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
+                              UINT64_MAX);
+  GNUNET_CONTAINER_DLL_insert (idp->issue_op_head,
+                               idp->issue_op_tail,
+                               ih);
+  bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
+  GNUNET_SERVICE_client_continue (idp->client);
+
+}
+
+/**********************************************************
+ * Revocation
+ **********************************************************/
+
+/**
+ * Cleanup revoke handle
+ *
+ * @param rh the ticket revocation handle
+ */
+static void
+cleanup_revoke_ticket_handle (struct TicketRevocationHandle *rh)
+{
+  if (NULL != rh->attrs)
+    GNUNET_RECLAIM_ATTRIBUTE_list_destroy (rh->attrs);
+  if (NULL != rh->rvk_attrs)
+    GNUNET_RECLAIM_ATTRIBUTE_list_destroy (rh->rvk_attrs);
+  if (NULL != rh->abe_key)
+    GNUNET_ABE_cpabe_delete_master_key (rh->abe_key);
+  if (NULL != rh->ns_qe)
+    GNUNET_NAMESTORE_cancel (rh->ns_qe);
+  if (NULL != rh->ns_it)
+    GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
+  GNUNET_free (rh);
+}
+
+
+/**
+ * Send revocation result
+ *
+ * @param rh ticket revocation handle
+ * @param success GNUNET_OK if successful result
+ */
+static void
+send_revocation_finished (struct TicketRevocationHandle *rh,
+                          uint32_t success)
+{
+  struct GNUNET_MQ_Envelope *env;
+  struct RevokeTicketResultMessage *trm;
+  
+  GNUNET_break(TKT_database->delete_ticket (TKT_database->cls,
+                                            &rh->ticket));
+
+  env = GNUNET_MQ_msg (trm,
+                       GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
+  trm->id = htonl (rh->r_id);
+  trm->success = htonl (success);
+  GNUNET_MQ_send (rh->client->mq,
+                  env);
+  GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head,
+                               rh->client->revoke_op_tail,
+                               rh);
+}
+
+
+/**
+ * Process ticket from database
+ *
+ * @param cls struct TicketIterationProcResult
+ * @param ticket the ticket
+ * @param attrs the attributes
+ */
+static void
+ticket_reissue_proc (void *cls,
+                     const struct GNUNET_RECLAIM_Ticket *ticket,
+                     const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs);
+
+static void
+revocation_reissue_tickets (struct TicketRevocationHandle *rh);
+
+
+static void reissue_next (void *cls)
+{
+  struct TicketRevocationHandle *rh = cls;
+  revocation_reissue_tickets (rh);
+}
+
+
+static void
+reissue_ticket_cont (void *cls,
+                     int32_t success,
+                     const char *emsg)
+{
+  struct TicketRevocationHandle *rh = cls;
+
+  rh->ns_qe = NULL;
+  if (GNUNET_SYSERR == success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
+                "Unknown Error\n");
+    send_revocation_finished (rh, GNUNET_SYSERR);
+    cleanup_revoke_ticket_handle (rh);
+    return;
+  }
+  rh->offset++;
+  GNUNET_SCHEDULER_add_now (&reissue_next, rh);
+}
+
+
+/**
+ * Process ticket from database
+ *
+ * @param cls struct TicketIterationProcResult
+ * @param ticket the ticket
+ * @param attrs the attributes
+ */
+static void
+ticket_reissue_proc (void *cls,
+                     const struct GNUNET_RECLAIM_Ticket *ticket,
+                     const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
+{
+  struct TicketRevocationHandle *rh = cls;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le_rollover;
+  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
+  struct GNUNET_GNSRECORD_Data code_record[1];
+  struct GNUNET_ABE_AbeKey *rp_key;
+  char *code_record_data;
+  char **attr_arr;
+  char *label;
+  char *policy;
+  int attrs_len;
+  uint32_t i;
+  int reissue_ticket;
+  size_t code_record_len;
+
+
+  if (NULL == ticket)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Iteration done\n");
+    return;
+  }
+
+  if (0 == memcmp (&ticket->audience,
+                   &rh->ticket.audience,
+                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Do not reissue for this identity.!\n");
+    label = GNUNET_STRINGS_data_to_string_alloc (&rh->ticket.rnd,
+                                                 sizeof (uint64_t));
+    //Delete record
+    rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                                &rh->identity,
+                                                label,
+                                                0,
+                                                NULL,
+                                                &reissue_ticket_cont,
+                                                rh);
+
+    GNUNET_free (label);
+    return;
+  }
+
+  /* 
+   * Check if any attribute of this ticket intersects with a rollover attribute
+   */
+  reissue_ticket = GNUNET_NO;
+  for (le = attrs->list_head; NULL != le; le = le->next)
+  {
+    for (le_rollover = rh->rvk_attrs->list_head;
+         NULL != le_rollover;
+         le_rollover = le_rollover->next)
+    {
+      if (0 == strcmp (le_rollover->claim->name,
+                       le->claim->name))
+      {
+        reissue_ticket = GNUNET_YES;
+        le->claim->version = le_rollover->claim->version;
+      }
+    }
+  }
+
+  if (GNUNET_NO == reissue_ticket)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Skipping ticket.\n");
+
+    rh->offset++;
+    GNUNET_SCHEDULER_add_now (&reissue_next, rh);
+
+
+    return;
+  }
+
+  //Create new ABE key for RP
+  attrs_len = 0;
+
+  /* If this is the RP we want to revoke attributes of, the do so */
+
+  for (le = attrs->list_head; NULL != le; le = le->next)
+    attrs_len++;
+  attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
+  i = 0;
+  for (le = attrs->list_head; NULL != le; le = le->next) {
+    GNUNET_asprintf (&policy, "%s_%lu",
+                     le->claim->name,
+                     le->claim->version);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Recreating key with %s\n", policy);
+    attr_arr[i] = policy;
+    i++;
+  }
+  attr_arr[i] = NULL;
+  rp_key = GNUNET_ABE_cpabe_create_key (rh->abe_key,
+                                        attr_arr);
+
+  //TODO review this wireformat
+  code_record_len = serialize_abe_keyinfo2 (ticket,
+                                            attrs,
+                                            rp_key,
+                                            &ecdhe_privkey,
+                                            &code_record_data);
+  code_record[0].data = code_record_data;
+  code_record[0].data_size = code_record_len;
+  code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
+  code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
+  code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+
+  label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
+                                               sizeof (uint64_t));
+  //Publish record
+  rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                              &rh->identity,
+                                              label,
+                                              1,
+                                              code_record,
+                                              &reissue_ticket_cont,
+                                              rh);
+  //for (; i > 0; i--)
+  //  GNUNET_free (attr_arr[i-1]);
+  GNUNET_free (ecdhe_privkey);
+  GNUNET_free (label);
+  GNUNET_free (attr_arr);
+  GNUNET_free (code_record_data);
+  GNUNET_ABE_cpabe_delete_key (rp_key, GNUNET_YES);
+}
+
+
+/* Prototype for below function */
+static void
+attr_reenc_cont (void *cls,
+                 int32_t success,
+                 const char *emsg);
+
+static void
+revocation_reissue_tickets (struct TicketRevocationHandle *rh)
+{
+  int ret;
+  /* Done, issue new keys */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Revocation Phase III: Reissuing Tickets\n");
+  if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
+                                                             &rh->ticket.identity,
+                                                             GNUNET_NO,
+                                                             rh->offset,
+                                                             &ticket_reissue_proc,
+                                                             rh)))
+  {
+    GNUNET_break (0);
+  }
+  if (GNUNET_NO == ret)
+  {
+    send_revocation_finished (rh, GNUNET_OK);
+    cleanup_revoke_ticket_handle (rh);
+    return;
+  }
+}
+
+/**
+ * Failed to check for attribute
+ */
+static void
+check_attr_error (void *cls)
+{
+  struct TicketRevocationHandle *rh = cls;
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Unable to check for existing attribute\n");
+  rh->ns_qe = NULL;
+  send_revocation_finished (rh, GNUNET_SYSERR);
+  cleanup_revoke_ticket_handle (rh);
+}
+
+
+/**
+ * Revoke next attribte by reencryption with
+ * new ABE master
+ */
+static void
+reenc_next_attribute (void *cls);
+
+/**
+ * Check for existing attribute and overwrite
+ */
+static void
+check_attr_cb (void *cls,
+               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+               const char *label,
+               unsigned int rd_count,
+               const struct GNUNET_GNSRECORD_Data *rd_old)
+{
+  struct TicketRevocationHandle *rh = cls;
+  struct GNUNET_GNSRECORD_Data rd[1];
+  char* buf;
+  char* enc_buf;
+  size_t enc_size;
+  char* rd_buf;
+  size_t buf_size;
+  char* policy;
+  uint32_t attr_ver;
+
+  rh->ns_qe = NULL;
+  if (1 != rd_count) {
+    GNUNET_SCHEDULER_add_now (&reenc_next_attribute,
+                              rh);
+    return;
+  }
+
+  buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim);
+  buf = GNUNET_malloc (buf_size);
+  GNUNET_RECLAIM_ATTRIBUTE_serialize (rh->attrs->list_head->claim,
+                                       buf);
+  rh->attrs->list_head->claim->version++;
+  GNUNET_asprintf (&policy, "%s_%lu",
+                   rh->attrs->list_head->claim->name,
+                   rh->attrs->list_head->claim->version);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Encrypting with policy %s\n", policy);
+  /**
+   * Encrypt the attribute value and store in namestore
+   */
+  enc_size = GNUNET_ABE_cpabe_encrypt (buf,
+                                       buf_size,
+                                       policy, //Policy
+                                       rh->abe_key,
+                                       (void**)&enc_buf);
+  GNUNET_free (buf);
+  if (GNUNET_SYSERR == enc_size)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to re-encrypt with policy %s\n",
+                policy);
+    GNUNET_free (policy);
+    send_revocation_finished (rh, GNUNET_SYSERR);
+    cleanup_revoke_ticket_handle (rh);
+    return;
+  }
+  GNUNET_free (policy);
+
+  rd[0].data_size = enc_size + sizeof (uint32_t);
+  rd_buf = GNUNET_malloc (rd[0].data_size);
+  attr_ver = htonl (rh->attrs->list_head->claim->version);
+  GNUNET_memcpy (rd_buf,
+                 &attr_ver,
+                 sizeof (uint32_t));
+  GNUNET_memcpy (rd_buf+sizeof (uint32_t),
+                 enc_buf,
+                 enc_size);
+  rd[0].data = rd_buf;
+  rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
+  rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+  rd[0].expiration_time = rd_old[0].expiration_time;
+  rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                              &rh->identity,
+                                              rh->attrs->list_head->claim->name,
+                                              1,
+                                              rd,
+                                              &attr_reenc_cont,
+                                              rh);
+  GNUNET_free (enc_buf);
+  GNUNET_free (rd_buf);
+}
+
+
+/**
+ * Revoke next attribte by reencryption with
+ * new ABE master
+ */
+static void
+reenc_next_attribute (void *cls)
+{
+  struct TicketRevocationHandle *rh = cls;
+  if (NULL == rh->attrs->list_head)
+  {
+    revocation_reissue_tickets (rh);
+    return;
+  }
+  /* First check if attribute still exists */
+  rh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
+                                               &rh->identity,
+                                               rh->attrs->list_head->claim->name,
+                                               &check_attr_error,
+                                               rh,
+                                               &check_attr_cb,
+                                               rh);
+}
+
+
+/**
+ * Namestore callback after revoked attribute
+ * is stored
+ */
+static void
+attr_reenc_cont (void *cls,
+                 int32_t success,
+                 const char *emsg)
+{
+  struct TicketRevocationHandle *rh = cls;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+
+  rh->ns_qe = NULL;
+  if (GNUNET_SYSERR == success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to reencrypt attribute %s\n",
+                emsg);
+    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+    return;
+  }
+  if (NULL == rh->attrs->list_head)
+  {
+    revocation_reissue_tickets (rh);
+    return;
+  }
+  le = rh->attrs->list_head;
+  GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
+                               rh->attrs->list_tail,
+                               le);
+  GNUNET_assert (NULL != rh->rvk_attrs);
+  GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
+                               rh->rvk_attrs->list_tail,
+                               le);
+
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Re-encrypting next attribute\n");
+  reenc_next_attribute (rh);
+}
+
+
+static void
+process_attributes_to_update (void *cls,
+                              const struct GNUNET_RECLAIM_Ticket *ticket,
+                              const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
+{
+  struct TicketRevocationHandle *rh = cls;
+
+  rh->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (attrs);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Revocation Phase I: Collecting attributes\n");
+  /* Reencrypt all attributes with new key */
+  if (NULL == rh->attrs->list_head)
+  {
+    /* No attributes to reencrypt */
+    send_revocation_finished (rh, GNUNET_OK);
+    cleanup_revoke_ticket_handle (rh);
+    return;
+  } else {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Revocation Phase II: Re-encrypting attributes\n");
+    reenc_next_attribute (rh);
+  }
+
+}
+
+
+
+static void
+get_ticket_after_abe_bootstrap (void *cls,
+                                struct GNUNET_ABE_AbeMasterKey *abe_key)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Finished ABE bootstrap\n");
+  struct TicketRevocationHandle *rh = cls;
+  rh->abe_key = abe_key;
+  TKT_database->get_ticket_attributes (TKT_database->cls,
+                                       &rh->ticket,
+                                       &process_attributes_to_update,
+                                       rh);
+}
+
+static int
+check_revoke_ticket_message(void *cls,
+                            const struct RevokeTicketMessage *im)
+{
+  uint16_t size;
+
+  size = ntohs (im->header.size);
+  if (size <= sizeof (struct RevokeTicketMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+static void
+handle_revoke_ticket_message (void *cls,
+                              const struct RevokeTicketMessage *rm)
+{
+  struct TicketRevocationHandle *rh;
+  struct IdpClient *idp = cls;
+  struct GNUNET_RECLAIM_Ticket *ticket;
+
+  rh = GNUNET_new (struct TicketRevocationHandle);
+  ticket = (struct GNUNET_RECLAIM_Ticket*)&rm[1];
+  rh->rvk_attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
+  rh->ticket = *ticket;
+  rh->r_id = ntohl (rm->id);
+  rh->client = idp;
+  rh->identity = rm->identity;
+  GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
+                                      &rh->ticket.identity);
+  GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head,
+                               idp->revoke_op_tail,
+                               rh);
+  bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO);
+  GNUNET_SERVICE_client_continue (idp->client);
+
+}
+
+/**
+ * Cleanup ticket consume handle
+ * @param handle the handle to clean up
+ */
+static void
+cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
+{
+  struct ParallelLookup *lu;  
+  struct ParallelLookup *tmp;
+  if (NULL != handle->lookup_request)
+    GNUNET_GNS_lookup_cancel (handle->lookup_request);
+  for (lu = handle->parallel_lookups_head;
+       NULL != lu;) {
+    GNUNET_GNS_lookup_cancel (lu->lookup_request);
+    GNUNET_free (lu->label);
+    tmp = lu->next;
+    GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
+                                 handle->parallel_lookups_tail,
+                                 lu);
+    GNUNET_free (lu);
+    lu = tmp;
+  }
+
+  if (NULL != handle->key)
+    GNUNET_ABE_cpabe_delete_key (handle->key,
+                                 GNUNET_YES);
+  if (NULL != handle->attrs)
+    GNUNET_RECLAIM_ATTRIBUTE_list_destroy (handle->attrs);
+  GNUNET_free (handle);
+}
+
+
+
+static int
+check_consume_ticket_message(void *cls,
+                             const struct ConsumeTicketMessage *cm)
+{
+  uint16_t size;
+
+  size = ntohs (cm->header.size);
+  if (size <= sizeof (struct ConsumeTicketMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+static void
+process_parallel_lookup2 (void *cls, uint32_t rd_count,
+                          const struct GNUNET_GNSRECORD_Data *rd)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Parallel lookup finished (count=%u)\n", rd_count);
+  struct ParallelLookup *parallel_lookup = cls;
+  struct ConsumeTicketHandle *handle = parallel_lookup->handle;
+  struct ConsumeTicketResultMessage *crm;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *attr_le;
+  struct GNUNET_TIME_Absolute decrypt_duration;
+  char *data;
+  char *data_tmp;
+  ssize_t attr_len;
+  size_t attrs_len;
+
+  GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
+                               handle->parallel_lookups_tail,
+                               parallel_lookup);
+  GNUNET_free (parallel_lookup->label);
+
+  GNUNET_STATISTICS_update (stats,
+                            "attribute_lookup_time_total",
+                            GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us,
+                            GNUNET_YES);
+  GNUNET_STATISTICS_update (stats,
+                            "attribute_lookups_count",
+                            1,
+                            GNUNET_YES);
+
+
+  GNUNET_free (parallel_lookup);
+  if (1 != rd_count)
+    GNUNET_break(0);//TODO
+  if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
+  {
+    decrypt_duration = GNUNET_TIME_absolute_get ();
+    attr_len = GNUNET_ABE_cpabe_decrypt (rd->data + sizeof (uint32_t),
+                                         rd->data_size - sizeof (uint32_t),
+                                         handle->key,
+                                         (void**)&data);
+    if (GNUNET_SYSERR != attr_len) 
+    {
+      GNUNET_STATISTICS_update (stats,
+                                "abe_decrypt_time_total",
+                                GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us,
+                                GNUNET_YES);
+      GNUNET_STATISTICS_update (stats,
+                                "abe_decrypt_count",
+                                1,
+                                GNUNET_YES);
+
+      attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+      attr_le->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize (data,
+                                                              attr_len);
+      attr_le->claim->version = ntohl(*(uint32_t*)rd->data);
+      GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
+                                   handle->attrs->list_tail,
+                                   attr_le);
+      GNUNET_free (data);
+    }
+  }
+  if (NULL != handle->parallel_lookups_head)
+    return; //Wait for more
+  /* Else we are done */
+
+  /* Store ticket in DB */
+  if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
+                                               &handle->ticket,
+                                               handle->attrs))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to store ticket after consume\n");
+    GNUNET_break (0);
+  }
+
+  GNUNET_SCHEDULER_cancel (handle->kill_task);
+  attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (handle->attrs);
+  env = GNUNET_MQ_msg_extra (crm,
+                             attrs_len,
+                             GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
+  crm->id = htonl (handle->r_id);
+  crm->attrs_len = htons (attrs_len);
+  crm->identity = handle->ticket.identity;
+  data_tmp = (char *) &crm[1];
+  GNUNET_RECLAIM_ATTRIBUTE_list_serialize (handle->attrs,
+                                            data_tmp);
+  GNUNET_MQ_send (handle->client->mq, env);
+  GNUNET_CONTAINER_DLL_remove (handle->client->consume_op_head,
+                               handle->client->consume_op_tail,
+                               handle);
+  cleanup_consume_ticket_handle (handle);
+}
+
+void
+abort_parallel_lookups2 (void *cls)
+{
+  struct ConsumeTicketHandle *handle = cls;
+  struct ParallelLookup *lu;
+  struct ParallelLookup *tmp;
+  struct AttributeResultMessage *arm;
+  struct GNUNET_MQ_Envelope *env;
+
+  handle->kill_task = NULL;
+  for (lu = handle->parallel_lookups_head;
+       NULL != lu;) {
+    GNUNET_GNS_lookup_cancel (lu->lookup_request);
+    GNUNET_free (lu->label);
+    tmp = lu->next;
+    GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
+                                 handle->parallel_lookups_tail,
+                                 lu);
+    GNUNET_free (lu);
+    lu = tmp;
+  }
+  env = GNUNET_MQ_msg (arm,
+                       GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
+  arm->id = htonl (handle->r_id);
+  arm->attr_len = htons (0);
+  GNUNET_MQ_send (handle->client->mq, env);
+
+}
+
+
+static void
+process_consume_abe_key (void *cls, uint32_t rd_count,
+                         const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct ConsumeTicketHandle *handle = cls;
+  struct GNUNET_HashCode new_key_hash;
+  struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
+  struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
+  struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
+  struct ParallelLookup *parallel_lookup;
+  size_t size;
+  char *buf;
+  char *scope;
+
+  handle->lookup_request = NULL;
+  if (1 != rd_count)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Number of keys %d != 1.",
+                rd_count);
+    cleanup_consume_ticket_handle (handle);
+    GNUNET_CONTAINER_DLL_remove (handle->client->consume_op_head,
+                                 handle->client->consume_op_tail,
+                                 handle);
+    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+    return;
+  }
+
+  //Decrypt
+  ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
+
+  buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+
+  //Calculate symmetric key from ecdh parameters
+  GNUNET_assert (GNUNET_OK == 
+                 GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
+                                           ecdh_key,
+                                           &new_key_hash));
+  create_sym_key_from_ecdh (&new_key_hash,
+                            &enc_key,
+                            &enc_iv);
+  size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
+                                          rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
+                                          &enc_key,
+                                          &enc_iv,
+                                          buf);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Decrypted bytes: %zd Expected bytes: %zd\n",
+              size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+  GNUNET_STATISTICS_update (stats,
+                            "abe_key_lookup_time_total",
+                            GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us,
+                            GNUNET_YES);
+  GNUNET_STATISTICS_update (stats,
+                            "abe_key_lookups_count",
+                            1,
+                            GNUNET_YES);
+  scopes = GNUNET_strdup (buf);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Scopes %s\n", scopes);
+  handle->key = GNUNET_ABE_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
+                                                  rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
+                                                  - strlen (scopes) - 1);
+
+  for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Looking up %s\n", scope);
+    parallel_lookup = GNUNET_new (struct ParallelLookup);
+    parallel_lookup->handle = handle;
+    parallel_lookup->label = GNUNET_strdup (scope);
+    parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get();
+    parallel_lookup->lookup_request
+      = GNUNET_GNS_lookup (gns_handle,
+                           scope,
+                           &handle->ticket.identity,
+                           GNUNET_GNSRECORD_TYPE_ID_ATTR,
+                           GNUNET_GNS_LO_DEFAULT,
+                           &process_parallel_lookup2,
+                           parallel_lookup);
+    GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
+                                 handle->parallel_lookups_tail,
+                                 parallel_lookup);
+  }
+  GNUNET_free (scopes);
+  GNUNET_free (buf);
+  handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
+                                                    &abort_parallel_lookups2,
+                                                    handle);
+}
+
+
+static void
+handle_consume_ticket_message (void *cls,
+                               const struct ConsumeTicketMessage *cm)
+{
+  struct ConsumeTicketHandle *ch;
+  struct IdpClient *idp = cls;
+  char* rnd_label;
+
+  ch = GNUNET_new (struct ConsumeTicketHandle);
+  ch->r_id = ntohl (cm->id);
+  ch->client = idp;
+  ch->identity = cm->identity;
+  ch->attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
+  GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
+                                      &ch->identity_pub);
+  ch->ticket = *((struct GNUNET_RECLAIM_Ticket*)&cm[1]);
+  rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
+                                                   sizeof (uint64_t));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Looking for ABE key under %s\n", rnd_label);
+  ch->lookup_start_time = GNUNET_TIME_absolute_get ();
+  ch->lookup_request
+    = GNUNET_GNS_lookup (gns_handle,
+                         rnd_label,
+                         &ch->ticket.identity,
+                         GNUNET_GNSRECORD_TYPE_ABE_KEY,
+                         GNUNET_GNS_LO_DEFAULT,
+                         &process_consume_abe_key,
+                         ch);
+  GNUNET_CONTAINER_DLL_insert (idp->consume_op_head,
+                               idp->consume_op_tail,
+                               ch);
+  GNUNET_free (rnd_label);
+  GNUNET_SERVICE_client_continue (idp->client);
+}
+
+/**
+ * Cleanup attribute store handle
+ *
+ * @param handle handle to clean up
+ */
+static void
+cleanup_as_handle (struct AttributeStoreHandle *handle)
+{
+  if (NULL != handle->ns_qe)
+    GNUNET_NAMESTORE_cancel (handle->ns_qe);
+  if (NULL != handle->claim)
+    GNUNET_free (handle->claim);
+  if (NULL != handle->abe_key)
+    GNUNET_ABE_cpabe_delete_master_key (handle->abe_key);
+  GNUNET_free (handle);
+}
+
+static void
+attr_store_cont (void *cls,
+                 int32_t success,
+                 const char *emsg)
+{
+  struct AttributeStoreHandle *as_handle = cls;
+  struct GNUNET_MQ_Envelope *env;
+  struct AttributeStoreResultMessage *acr_msg;
+
+  as_handle->ns_qe = NULL;
+  GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head,
+                               as_handle->client->store_op_tail,
+                               as_handle);
+
+  if (GNUNET_SYSERR == success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to store attribute %s\n",
+                emsg);
+    cleanup_as_handle (as_handle);
+    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending ATTRIBUTE_STORE_RESPONSE message\n");
+  env = GNUNET_MQ_msg (acr_msg,
+                       GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE_RESPONSE);
+  acr_msg->id = htonl (as_handle->r_id);
+  acr_msg->op_result = htonl (GNUNET_OK);
+  GNUNET_MQ_send (as_handle->client->mq,
+                  env);
+  cleanup_as_handle (as_handle);
+}
+
+static void
+attr_store_task (void *cls)
+{
+  struct AttributeStoreHandle *as_handle = cls;
+  struct GNUNET_GNSRECORD_Data rd[1];
+  char* buf;
+  char* policy;
+  char* enc_buf;
+  char* rd_buf;
+  size_t enc_size;
+  size_t buf_size;
+  uint32_t attr_ver;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Storing attribute\n");
+  buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (as_handle->claim);
+  buf = GNUNET_malloc (buf_size);
+
+  GNUNET_RECLAIM_ATTRIBUTE_serialize (as_handle->claim,
+                                       buf);
+
+  GNUNET_asprintf (&policy,
+                   "%s_%lu",
+                   as_handle->claim->name,
+                   as_handle->claim->version);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Encrypting with policy %s\n", policy);
+  /**
+   * Encrypt the attribute value and store in namestore
+   */
+  enc_size = GNUNET_ABE_cpabe_encrypt (buf,
+                                       buf_size,
+                                       policy, //Policy
+                                       as_handle->abe_key,
+                                       (void**)&enc_buf);
+  if (GNUNET_SYSERR == enc_size)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to encrypt with policy %s\n",
+                policy);
+    GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head,
+                                 as_handle->client->store_op_tail,
+                                 as_handle);
+
+    cleanup_as_handle (as_handle);
+    GNUNET_free (buf);
+    GNUNET_free (policy);
+    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+    return;
+  }
+  GNUNET_free (buf);
+  GNUNET_free (policy);
+  rd[0].data_size = enc_size + sizeof (uint32_t);
+  rd_buf = GNUNET_malloc (rd[0].data_size);
+  attr_ver = htonl (as_handle->claim->version);
+  GNUNET_memcpy (rd_buf,
+                 &attr_ver,
+                 sizeof (uint32_t));
+  GNUNET_memcpy (rd_buf+sizeof (uint32_t),
+                 enc_buf,
+                 enc_size);
+  rd[0].data = rd_buf;
+  rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
+  rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+  rd[0].expiration_time = as_handle->exp.rel_value_us;
+  as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                                     &as_handle->identity,
+                                                     as_handle->claim->name,
+                                                     1,
+                                                     rd,
+                                                     &attr_store_cont,
+                                                     as_handle);
+  GNUNET_free (enc_buf);
+  GNUNET_free (rd_buf);
+}
+
+
+static void
+store_after_abe_bootstrap (void *cls,
+                           struct GNUNET_ABE_AbeMasterKey *abe_key)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Finished ABE bootstrap\n");
+  struct AttributeStoreHandle *ash = cls;
+  ash->abe_key = abe_key;
+  GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
+}
+
+static int
+check_attribute_store_message(void *cls,
+                              const struct AttributeStoreMessage *sam)
+{
+  uint16_t size;
+
+  size = ntohs (sam->header.size);
+  if (size <= sizeof (struct AttributeStoreMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+static void
+handle_attribute_store_message (void *cls,
+                                const struct AttributeStoreMessage *sam)
+{
+  struct AttributeStoreHandle *as_handle;
+  struct IdpClient *idp = cls;
+  size_t data_len;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received ATTRIBUTE_STORE message\n");
+
+  data_len = ntohs (sam->attr_len);
+
+  as_handle = GNUNET_new (struct AttributeStoreHandle);
+  as_handle->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char*)&sam[1],
+                                                            data_len);
+
+  as_handle->r_id = ntohl (sam->id);
+  as_handle->identity = sam->identity;
+  as_handle->exp.rel_value_us = GNUNET_ntohll (sam->exp);
+  GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
+                                      &as_handle->identity_pkey);
+
+  GNUNET_SERVICE_client_continue (idp->client);
+  as_handle->client = idp;
+  GNUNET_CONTAINER_DLL_insert (idp->store_op_head,
+                               idp->store_op_tail,
+                               as_handle);
+  bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
+}
+
+static void
+cleanup_attribute_iter_handle (struct AttributeIterator *ai)
+{
+  if (NULL != ai->abe_key)
+    GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
+  GNUNET_free (ai);
+}
+
+static void
+attr_iter_error (void *cls)
+{
+  struct AttributeIterator *ai = cls;
+  //TODO
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Failed to iterate over attributes\n");
+  GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
+                               ai->client->attr_iter_tail,
+                               ai);
+  cleanup_attribute_iter_handle (ai);
+  GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+}
+
+static void
+attr_iter_finished (void *cls)
+{
+  struct AttributeIterator *ai = cls;
+  struct GNUNET_MQ_Envelope *env;
+  struct AttributeResultMessage *arm;
+
+  env = GNUNET_MQ_msg (arm,
+                       GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
+  arm->id = htonl (ai->request_id);
+  arm->attr_len = htons (0);
+  GNUNET_MQ_send (ai->client->mq, env);
+  GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
+                               ai->client->attr_iter_tail,
+                               ai);
+  cleanup_attribute_iter_handle (ai);
+}
+
+static void
+attr_iter_cb (void *cls,
+              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+              const char *label,
+              unsigned int rd_count,
+              const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct AttributeIterator *ai = cls;
+  struct AttributeResultMessage *arm;
+  struct GNUNET_ABE_AbeKey *key;
+  struct GNUNET_MQ_Envelope *env;
+  ssize_t msg_extra_len;
+  char* attr_ser;
+  char* attrs[2];
+  char* data_tmp;
+  char* policy;
+  uint32_t attr_ver;
+
+  if (rd_count != 1)
+  {
+    GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
+                                         1);
+    return;
+  }
+
+  if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type)
+  {
+    GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
+                                         1);
+    return;
+  }
+  attr_ver = ntohl(*((uint32_t*)rd->data));
+  GNUNET_asprintf (&policy, "%s_%lu",
+                   label, attr_ver);
+  attrs[0] = policy;
+  attrs[1] = 0;
+  key = GNUNET_ABE_cpabe_create_key (ai->abe_key,
+                                     attrs);
+  msg_extra_len = GNUNET_ABE_cpabe_decrypt (rd->data+sizeof (uint32_t),
+                                            rd->data_size-sizeof (uint32_t),
+                                            key,
+                                            (void**)&attr_ser);
+  if (GNUNET_SYSERR == msg_extra_len)
+  {
+    GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
+                                         1);
+    return;
+  }
+
+  GNUNET_ABE_cpabe_delete_key (key,
+                               GNUNET_YES);
+  //GNUNET_free (policy);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Found attribute: %s\n", label);
+  env = GNUNET_MQ_msg_extra (arm,
+                             msg_extra_len,
+                             GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
+  arm->id = htonl (ai->request_id);
+  arm->attr_len = htons (msg_extra_len);
+  GNUNET_CRYPTO_ecdsa_key_get_public (zone,
+                                      &arm->identity);
+  data_tmp = (char *) &arm[1];
+  GNUNET_memcpy (data_tmp,
+                 attr_ser,
+                 msg_extra_len);
+  GNUNET_MQ_send (ai->client->mq, env);
+  GNUNET_free (attr_ser);
+  GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
+  ai->abe_key = NULL;
+}
+
+
+void
+iterate_after_abe_bootstrap (void *cls,
+                             struct GNUNET_ABE_AbeMasterKey *abe_key)
+{
+  struct AttributeIterator *ai = cls;
+  ai->abe_key = abe_key;
+  ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
+                                                     &ai->identity,
+                                                     &attr_iter_error,
+                                                     ai,
+                                                     &attr_iter_cb,
+                                                     ai,
+                                                     &attr_iter_finished,
+                                                     ai);
+}
+
+
+static void
+iterate_next_after_abe_bootstrap (void *cls,
+                                  struct GNUNET_ABE_AbeMasterKey *abe_key)
+{
+  struct AttributeIterator *ai = cls;
+  ai->abe_key = abe_key;
+  GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it,
+                                       1);
+}
+
+
+
+static void
+handle_iteration_start (void *cls,
+                        const struct AttributeIterationStartMessage *ais_msg)
+{
+  struct IdpClient *idp = cls;
+  struct AttributeIterator *ai;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received ATTRIBUTE_ITERATION_START message\n");
+  ai = GNUNET_new (struct AttributeIterator);
+  ai->request_id = ntohl (ais_msg->id);
+  ai->client = idp;
+  ai->identity = ais_msg->identity;
+
+  GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head,
+                               idp->attr_iter_tail,
+                               ai);
+  bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
+  GNUNET_SERVICE_client_continue (idp->client);
+}
+
+
+static void
+handle_iteration_stop (void *cls,
+                       const struct AttributeIterationStopMessage *ais_msg)
+{
+  struct IdpClient *idp = cls;
+  struct AttributeIterator *ai;
+  uint32_t rid;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received `%s' message\n",
+              "ATTRIBUTE_ITERATION_STOP");
+  rid = ntohl (ais_msg->id);
+  for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
+    if (ai->request_id == rid)
+      break;
+  if (NULL == ai)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (idp->client);
+    return;
+  }
+  GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head,
+                               idp->attr_iter_tail,
+                               ai);
+  GNUNET_free (ai);
+  GNUNET_SERVICE_client_continue (idp->client);
+}
+
+
+static void
+handle_iteration_next (void *cls,
+                       const struct AttributeIterationNextMessage *ais_msg)
+{
+  struct IdpClient *idp = cls;
+  struct AttributeIterator *ai;
+  uint32_t rid;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received ATTRIBUTE_ITERATION_NEXT message\n");
+  rid = ntohl (ais_msg->id);
+  for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
+    if (ai->request_id == rid)
+      break;
+  if (NULL == ai)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (idp->client);
+    return;
+  }
+  bootstrap_abe (&ai->identity,
+                 &iterate_next_after_abe_bootstrap,
+                 ai,
+                 GNUNET_NO);
+  GNUNET_SERVICE_client_continue (idp->client);
+}
+
+/**
+ * Ticket iteration processor result
+ */
+enum ZoneIterationResult
+{
+  /**
+   * Iteration start.
+   */
+  IT_START = 0,
+
+  /**
+   * Found tickets,
+   * Continue to iterate with next iteration_next call
+   */
+  IT_SUCCESS_MORE_AVAILABLE = 1,
+
+  /**
+   * Iteration complete
+   */
+  IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
+};
+
+
+/**
+ * Context for ticket iteration
+ */
+struct TicketIterationProcResult
+{
+  /**
+   * The ticket iteration handle
+   */
+  struct TicketIteration *ti;
+
+  /**
+   * Iteration result: iteration done?
+   * #IT_SUCCESS_MORE_AVAILABLE:  if there may be more results overall but
+   * we got one for now and have sent it to the client
+   * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
+   * #IT_START: if we are still trying to find a result.
+   */
+  int res_iteration_finished;
+
+};
+
+static void
+cleanup_ticket_iter_handle (struct TicketIteration *ti)
+{
+  GNUNET_free (ti);
+}
+
+/**
+ * Process ticket from database
+ *
+ * @param cls struct TicketIterationProcResult
+ * @param ticket the ticket
+ * @param attrs the attributes
+ */
+static void
+ticket_iterate_proc (void *cls,
+                     const struct GNUNET_RECLAIM_Ticket *ticket,
+                     const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
+{
+  struct TicketIterationProcResult *proc = cls;
+
+  if (NULL == ticket)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Iteration done\n");
+    proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
+    return;
+  }
+  proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
+  send_ticket_result (proc->ti->client,
+                      proc->ti->r_id,
+                      ticket,
+                      attrs);
+
+}
+
+/**
+ * Perform ticket iteration step
+ *
+ * @param ti ticket iterator to process
+ */
+static void
+run_ticket_iteration_round (struct TicketIteration *ti)
+{
+  struct TicketIterationProcResult proc;
+  struct GNUNET_MQ_Envelope *env;
+  struct TicketResultMessage *trm;
+  int ret;
+
+  memset (&proc, 0, sizeof (proc));
+  proc.ti = ti;
+  proc.res_iteration_finished = IT_START;
+  while (IT_START == proc.res_iteration_finished)
+  {
+    if (GNUNET_SYSERR ==
+        (ret = TKT_database->iterate_tickets (TKT_database->cls,
+                                              &ti->identity,
+                                              ti->is_audience,
+                                              ti->offset,
+                                              &ticket_iterate_proc,
+                                              &proc)))
+    {
+      GNUNET_break (0);
+      break;
+    }
+    if (GNUNET_NO == ret)
+      proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
+    ti->offset++;
+  }
+  if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "More results available\n");
+    return; /* more later */
+  }
+  /* send empty response to indicate end of list */
+  env = GNUNET_MQ_msg (trm,
+                       GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
+  trm->id = htonl (ti->r_id);
+  GNUNET_MQ_send (ti->client->mq,
+                  env);
+  GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
+                               ti->client->ticket_iter_tail,
+                               ti);
+  cleanup_ticket_iter_handle (ti);
+}
+
+static void
+handle_ticket_iteration_start (void *cls,
+                               const struct TicketIterationStartMessage *tis_msg)
+{
+  struct IdpClient *client = cls;
+  struct TicketIteration *ti;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received TICKET_ITERATION_START message\n");
+  ti = GNUNET_new (struct TicketIteration);
+  ti->r_id = ntohl (tis_msg->id);
+  ti->offset = 0;
+  ti->client = client;
+  ti->identity = tis_msg->identity;
+  ti->is_audience = ntohl (tis_msg->is_audience);
+
+  GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
+                               client->ticket_iter_tail,
+                               ti);
+  run_ticket_iteration_round (ti);
+  GNUNET_SERVICE_client_continue (client->client);
+}
+
+
+static void
+handle_ticket_iteration_stop (void *cls,
+                              const struct TicketIterationStopMessage *tis_msg)
+{
+  struct IdpClient *client = cls;
+  struct TicketIteration *ti;
+  uint32_t rid;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received `%s' message\n",
+              "TICKET_ITERATION_STOP");
+  rid = ntohl (tis_msg->id);
+  for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
+    if (ti->r_id == rid)
+      break;
+  if (NULL == ti)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (client->client);
+    return;
+  }
+  GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
+                               client->ticket_iter_tail,
+                               ti);
+  cleanup_ticket_iter_handle (ti);
+  GNUNET_SERVICE_client_continue (client->client);
+}
+
+
+static void
+handle_ticket_iteration_next (void *cls,
+                              const struct TicketIterationNextMessage *tis_msg)
+{
+  struct IdpClient *client = cls;
+  struct TicketIteration *ti;
+  uint32_t rid;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received TICKET_ITERATION_NEXT message\n");
+  rid = ntohl (tis_msg->id);
+  for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
+    if (ti->r_id == rid)
+      break;
+  if (NULL == ti)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (client->client);
+    return;
+  }
+  run_ticket_iteration_round (ti);
+  GNUNET_SERVICE_client_continue (client->client);
+}
+
+
+
+
+/**
+ * Main function that will be run
+ *
+ * @param cls closure
+ * @param c the configuration used 
+ * @param server the service handle
+ */
+static void
+run (void *cls,
+     const struct GNUNET_CONFIGURATION_Handle *c,
+     struct GNUNET_SERVICE_Handle *server)
+{
+  char *database;
+  cfg = c;
+
+  stats = GNUNET_STATISTICS_create ("reclaim", cfg);
+
+  //Connect to identity and namestore services
+  ns_handle = GNUNET_NAMESTORE_connect (cfg);
+  if (NULL == ns_handle)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
+  }
+
+  gns_handle = GNUNET_GNS_connect (cfg);
+  if (NULL == gns_handle)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
+  }
+  credential_handle = GNUNET_CREDENTIAL_connect (cfg);
+  if (NULL == credential_handle)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
+  }
+  identity_handle = GNUNET_IDENTITY_connect (cfg,
+                                             NULL,
+                                             NULL);
+  /* Loading DB plugin */
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             "reclaim",
+                                             "database",
+                                             &database))
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "No database backend configured\n");
+  GNUNET_asprintf (&db_lib_name,
+                   "libgnunet_plugin_reclaim_%s",
+                   database);
+  TKT_database = GNUNET_PLUGIN_load (db_lib_name,
+                                     (void *) cfg);
+  GNUNET_free (database);
+  if (NULL == TKT_database)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Could not load database backend `%s'\n",
+                db_lib_name);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_time (cfg,
+                                           "reclaim",
+                                           "TOKEN_EXPIRATION_INTERVAL",
+                                           &token_expiration_interval))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Time window for zone iteration: %s\n",
+                GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
+                                                        GNUNET_YES));
+  } else {
+    token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
+  }
+
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
+}
+
+/**
+ * Called whenever a client is disconnected.
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param app_ctx @a client
+ */
+static void
+client_disconnect_cb (void *cls,
+                      struct GNUNET_SERVICE_Client *client,
+                      void *app_ctx)
+{
+  struct IdpClient *idp = app_ctx;
+  struct AttributeIterator *ai;
+  struct TicketIteration *ti;
+  struct TicketRevocationHandle *rh;
+  struct TicketIssueHandle *iss;
+  struct ConsumeTicketHandle *ct;
+  struct AttributeStoreHandle *as;
+
+  //TODO other operations
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Client %p disconnected\n",
+              client);
+
+  while (NULL != (iss = idp->issue_op_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (idp->issue_op_head,
+                                 idp->issue_op_tail,
+                                 iss);
+    cleanup_ticket_issue_handle (iss);
+  }
+  while (NULL != (ct = idp->consume_op_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
+                                 idp->consume_op_tail,
+                                 ct);
+    cleanup_consume_ticket_handle (ct);
+  }
+  while (NULL != (as = idp->store_op_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (idp->store_op_head,
+                                 idp->store_op_tail,
+                                 as);
+    cleanup_as_handle (as);
+  }
+
+  while (NULL != (ai = idp->attr_iter_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head,
+                                 idp->attr_iter_tail,
+                                 ai);
+    cleanup_attribute_iter_handle (ai);
+  }
+  while (NULL != (rh = idp->revoke_op_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head,
+                                 idp->revoke_op_tail,
+                                 rh);
+    cleanup_revoke_ticket_handle (rh);
+  }
+  while (NULL != (ti = idp->ticket_iter_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
+                                 idp->ticket_iter_tail,
+                                 ti);
+    cleanup_ticket_iter_handle (ti);
+  }
+  GNUNET_free (idp);
+}
+
+
+/**
+ * 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 internal namestore client structure for this client
+ */
+static void *
+client_connect_cb (void *cls,
+                   struct GNUNET_SERVICE_Client *client,
+                   struct GNUNET_MQ_Handle *mq)
+{
+  struct IdpClient *idp;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Client %p connected\n",
+              client);
+  idp = GNUNET_new (struct IdpClient);
+  idp->client = client;
+  idp->mq = mq;
+  return idp;
+}
+
+
+
+/**
+ * Define "main" method using service macro.
+ */
+GNUNET_SERVICE_MAIN
+("reclaim",
+ GNUNET_SERVICE_OPTION_NONE,
+ &run,
+ &client_connect_cb,
+ &client_disconnect_cb,
+ NULL,
+ GNUNET_MQ_hd_var_size (attribute_store_message,
+                        GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
+                        struct AttributeStoreMessage,
+                        NULL),
+ GNUNET_MQ_hd_fixed_size (iteration_start, 
+                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
+                          struct AttributeIterationStartMessage,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (iteration_next, 
+                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
+                          struct AttributeIterationNextMessage,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (iteration_stop, 
+                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
+                          struct AttributeIterationStopMessage,
+                          NULL),
+ GNUNET_MQ_hd_var_size (issue_ticket_message,
+                        GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
+                        struct IssueTicketMessage,
+                        NULL),
+ GNUNET_MQ_hd_var_size (consume_ticket_message,
+                        GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
+                        struct ConsumeTicketMessage,
+                        NULL),
+ GNUNET_MQ_hd_fixed_size (ticket_iteration_start, 
+                          GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
+                          struct TicketIterationStartMessage,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (ticket_iteration_next, 
+                          GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
+                          struct TicketIterationNextMessage,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (ticket_iteration_stop, 
+                          GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
+                          struct TicketIterationStopMessage,
+                          NULL),
+ GNUNET_MQ_hd_var_size (revoke_ticket_message,
+                        GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
+                        struct RevokeTicketMessage,
+                        NULL),
+ GNUNET_MQ_handler_end());
+/* end of gnunet-service-reclaim.c */
diff --git a/src/reclaim/jwt.c b/src/reclaim/jwt.c
new file mode 100644 (file)
index 0000000..45b5d73
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2010-2015 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      or (at your option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      Affero General Public License for more details.
+     
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file reclaim/jwt.c
+ * @brief helper library for JSON-Web-Tokens
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_signatures.h"
+#include "gnunet_reclaim_attribute_lib.h"
+#include <jansson.h>
+
+
+#define JWT_ALG "alg"
+
+/* Use 512bit HMAC */
+#define JWT_ALG_VALUE "HS512"
+
+#define JWT_TYP "typ"
+
+#define JWT_TYP_VALUE "jwt"
+
+#define SERVER_ADDRESS "https://reclaim.id/api/openid/userinfo"
+
+static char*
+create_jwt_header(void)
+{
+  json_t *root;
+  char *json_str;
+
+  root = json_object ();
+  json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
+  json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
+
+  json_str = json_dumps (root, JSON_INDENT(1));
+  json_decref (root);
+  return json_str;
+}
+
+/**
+ * Create a JWT from attributes
+ *
+ * @param aud_key the public of the subject
+ * @param attrs the attribute list
+ * @param priv_key the key used to sign the JWT
+ * @return a new base64-encoded JWT string.
+ */
+char*
+jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                      const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
+                                                const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+                                                const struct GNUNET_CRYPTO_AuthKey *priv_key)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  struct GNUNET_HashCode signature;
+  char* audience;
+  char* subject;
+  char* header;
+  char* padding;
+  char* body_str;
+  char* result;
+  char* header_base64;
+  char* body_base64;
+  char* signature_target;
+  char* signature_base64;
+  char* attr_val_str;
+  json_t* body;
+
+  //exp REQUIRED time expired from config
+  //iat REQUIRED time now
+  //auth_time only if max_age
+  //nonce only if nonce
+  // OPTIONAL acr,amr,azp
+  subject = GNUNET_STRINGS_data_to_string_alloc (&sub_key,
+                                                sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  audience = GNUNET_STRINGS_data_to_string_alloc (aud_key,
+                                                  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  header = create_jwt_header ();
+  body = json_object ();
+  
+  //iss REQUIRED case sensitive server uri with https
+  //The issuer is the local reclaim instance (e.g. https://reclaim.id/api/openid)
+  json_object_set_new (body,
+                       "iss", json_string (SERVER_ADDRESS));
+  //sub REQUIRED public key identity, not exceed 255 ASCII  length
+  json_object_set_new (body,
+                       "sub", json_string (subject));
+  //aud REQUIRED public key client_id must be there
+  json_object_set_new (body,
+                       "aud", json_string (audience));
+  for (le = attrs->list_head; NULL != le; le = le->next)
+  {
+    attr_val_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (le->claim->type,
+                                                              le->claim->data,
+                                                              le->claim->data_size);
+    json_object_set_new (body,
+                         le->claim->name,
+                         json_string (attr_val_str));
+    GNUNET_free (attr_val_str);
+  }
+  body_str = json_dumps (body, JSON_INDENT(0));
+  json_decref (body);
+
+  GNUNET_STRINGS_base64_encode (header,
+                                strlen (header),
+                                &header_base64);
+  //Remove GNUNET padding of base64
+  padding = strtok(header_base64, "=");
+  while (NULL != padding)
+    padding = strtok(NULL, "=");
+
+  GNUNET_STRINGS_base64_encode (body_str,
+                                strlen (body_str),
+                                &body_base64);
+
+  //Remove GNUNET padding of base64
+  padding = strtok(body_base64, "=");
+  while (NULL != padding)
+    padding = strtok(NULL, "=");
+
+  GNUNET_free (subject);
+  GNUNET_free (audience);
+
+  /**
+   * Creating the JWT signature. This might not be
+   * standards compliant, check.
+   */
+  GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64);
+  GNUNET_CRYPTO_hmac (priv_key, signature_target, strlen (signature_target), &signature);
+  GNUNET_STRINGS_base64_encode ((const char*)&signature,
+                                sizeof (struct GNUNET_HashCode),
+                                &signature_base64);
+  GNUNET_asprintf (&result, "%s.%s.%s",
+                   header_base64, body_base64, signature_base64);
+
+  GNUNET_free (signature_target);
+  GNUNET_free (header);
+  GNUNET_free (body_str);
+  GNUNET_free (signature_base64);
+  GNUNET_free (body_base64);
+  GNUNET_free (header_base64);
+  return result;
+}
diff --git a/src/reclaim/jwt.h b/src/reclaim/jwt.h
new file mode 100644 (file)
index 0000000..4b0b01b
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef JWT_H
+#define JWT_H
+
+char*
+jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                      const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
+                                                const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+                                                const struct GNUNET_CRYPTO_AuthKey *priv_key);
+
+#endif
diff --git a/src/reclaim/plugin_gnsrecord_reclaim.c b/src/reclaim/plugin_gnsrecord_reclaim.c
new file mode 100644 (file)
index 0000000..0322df7
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2013, 2014 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file reclaim/plugin_gnsrecord_reclaim.c
+ * @brief gnsrecord plugin to provide the API for identity records
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_gnsrecord_lib.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 *
+value_to_string (void *cls,
+                 uint32_t type,
+                 const void *data,
+                 size_t data_size)
+{
+  const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
+  const struct GNUNET_CRYPTO_EcdsaPublicKey *audience_pubkey;
+  const char *scopes;
+  char *ecdhe_str;
+  char *aud_str;
+  char *result;
+
+  switch (type)
+  {
+    case GNUNET_GNSRECORD_TYPE_ID_ATTR:
+      return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
+    case GNUNET_GNSRECORD_TYPE_ID_TOKEN: //DEPRECATED
+      return GNUNET_strndup (data, data_size);
+    case GNUNET_GNSRECORD_TYPE_ABE_KEY:
+    case GNUNET_GNSRECORD_TYPE_ABE_MASTER:
+      return GNUNET_STRINGS_data_to_string_alloc (data, data_size); 
+    case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: //DEPRECATED
+        ecdhe_privkey = data;
+        audience_pubkey = data+sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
+        scopes =  (char*) audience_pubkey+(sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+        ecdhe_str = GNUNET_STRINGS_data_to_string_alloc (ecdhe_privkey,
+                                                        sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
+        aud_str = GNUNET_STRINGS_data_to_string_alloc (audience_pubkey,
+                                                       sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+        GNUNET_asprintf (&result,
+                         "%s;%s;%s",
+                         ecdhe_str, aud_str, scopes);
+        GNUNET_free (aud_str);
+        GNUNET_free (ecdhe_str);
+        return result;
+
+    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
+string_to_value (void *cls,
+                 uint32_t type,
+                 const char *s,
+                 void **data,
+                 size_t *data_size)
+{
+  char* ecdhe_str;
+  char* aud_keystr;
+  char* write_ptr;
+  char* tmp_tok;
+  char* str;
+
+  if (NULL == s)
+    return GNUNET_SYSERR;
+  switch (type)
+  {
+    case GNUNET_GNSRECORD_TYPE_ID_ATTR:
+      return GNUNET_STRINGS_string_to_data (s,
+                                            strlen (s),
+                                            *data,
+                                            *data_size);
+    case GNUNET_GNSRECORD_TYPE_ID_TOKEN:
+      *data = GNUNET_strdup (s);
+      *data_size = strlen (s);
+      return GNUNET_OK;
+    case GNUNET_GNSRECORD_TYPE_ABE_KEY:
+    case GNUNET_GNSRECORD_TYPE_ABE_MASTER:
+      return GNUNET_STRINGS_string_to_data (s,
+                                            strlen (s),
+                                            *data,
+                                            *data_size);
+    case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA:
+      tmp_tok = GNUNET_strdup (s);
+      ecdhe_str = strtok (tmp_tok, ";");
+      if (NULL == ecdhe_str)
+      {
+        GNUNET_free (tmp_tok);
+        return GNUNET_SYSERR;
+      }
+      aud_keystr = strtok (NULL, ";");
+      if (NULL == aud_keystr)
+      {
+        GNUNET_free (tmp_tok);
+        return GNUNET_SYSERR;
+      }
+      str = strtok (NULL, ";");
+      if (NULL == str)
+      {
+        GNUNET_free (tmp_tok);
+        return GNUNET_SYSERR;
+      }
+      *data_size = strlen (str) + 1
+        +sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
+        +sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
+      *data = GNUNET_malloc (*data_size);
+
+      write_ptr = *data;
+      GNUNET_STRINGS_string_to_data (ecdhe_str,
+                                     strlen (ecdhe_str),
+                                     write_ptr,
+                                     sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
+      write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
+      GNUNET_STRINGS_string_to_data (aud_keystr,
+                                     strlen (aud_keystr),
+                                     write_ptr,
+                                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+      write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
+      GNUNET_memcpy (write_ptr, str, strlen (str) + 1); //with 0-Terminator
+      GNUNET_free (tmp_tok);
+      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[] = {
+  { "ID_ATTR", GNUNET_GNSRECORD_TYPE_ID_ATTR },
+  { "ID_TOKEN", GNUNET_GNSRECORD_TYPE_ID_TOKEN },
+  { "ABE_KEY", GNUNET_GNSRECORD_TYPE_ABE_KEY },
+  { "ABE_MASTER", GNUNET_GNSRECORD_TYPE_ABE_MASTER },
+  { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA },
+  { NULL, UINT32_MAX }
+};
+
+
+/**
+ * Convert a type name (i.e. "AAAA") to the corresponding number.
+ *
+ * @param cls closure, unused
+ * @param dns_typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+static uint32_t
+typename_to_number (void *cls,
+                    const char *dns_typename)
+{
+  unsigned int i;
+
+  i=0;
+  while ( (NULL != name_map[i].name) &&
+          (0 != strcasecmp (dns_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 *
+number_to_typename (void *cls,
+                    uint32_t type)
+{
+  unsigned int i;
+
+  i=0;
+  while ( (NULL != name_map[i].name) &&
+          (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_reclaim_init (void *cls)
+{
+  struct GNUNET_GNSRECORD_PluginFunctions *api;
+
+  api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
+  api->value_to_string = &value_to_string;
+  api->string_to_value = &string_to_value;
+  api->typename_to_number = &typename_to_number;
+  api->number_to_typename = &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_reclaim_done (void *cls)
+{
+  struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
+
+  GNUNET_free (api);
+  return NULL;
+}
+
+/* end of plugin_gnsrecord_dns.c */
diff --git a/src/reclaim/plugin_reclaim_sqlite.c b/src/reclaim/plugin_reclaim_sqlite.c
new file mode 100644 (file)
index 0000000..b545a94
--- /dev/null
@@ -0,0 +1,734 @@
+ /*
+  * This file is part of GNUnet
+  * Copyright (C) 2009-2017 GNUnet e.V.
+  *
+  * GNUnet is free software: you can redistribute it and/or modify it
+  * under the terms of the GNU Affero General Public License as published
+  * by the Free Software Foundation, either version 3 of the License,
+  * or (at your option) any later version.
+  *
+  * GNUnet is distributed in the hope that it will be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Affero General Public License for more details.
+  *
+  * You should have received a copy of the GNU Affero General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  */
+
+/**
+ * @file reclaim/plugin_reclaim_sqlite.c
+ * @brief sqlite-based idp backend
+ * @author Martin Schanzenbach
+ */
+
+#include "platform.h"
+#include "gnunet_reclaim_service.h"
+#include "gnunet_reclaim_plugin.h"
+#include "gnunet_reclaim_attribute_lib.h"
+#include "gnunet_sq_lib.h"
+#include <sqlite3.h>
+
+/**
+ * After how many ms "busy" should a DB operation fail for good?  A
+ * low value makes sure that we are more responsive to requests
+ * (especially PUTs).  A high value guarantees a higher success rate
+ * (SELECTs in iterate can take several seconds despite LIMIT=1).
+ *
+ * The default value of 1s should ensure that users do not experience
+ * huge latencies while at the same time allowing operations to
+ * succeed with reasonable probability.
+ */
+#define BUSY_TIMEOUT_MS 1000
+
+
+/**
+ * Log an error message at log-level 'level' that indicates
+ * a failure of the command 'cmd' on file 'filename'
+ * with the message given by strerror(errno).
+ */
+#define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "reclaim", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
+
+#define LOG(kind,...) GNUNET_log_from (kind, "reclaim-sqlite", __VA_ARGS__)
+
+
+/**
+ * Context for all functions in this plugin.
+ */
+struct Plugin
+{
+
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Database filename.
+   */
+  char *fn;
+
+  /**
+   * Native SQLite database handle.
+   */
+  sqlite3 *dbh;
+
+  /**
+   * Precompiled SQL to store ticket.
+   */
+  sqlite3_stmt *store_ticket;
+
+  /**
+   * Precompiled SQL to delete existing ticket.
+   */
+  sqlite3_stmt *delete_ticket;
+
+  /**
+   * Precompiled SQL to iterate tickets.
+   */
+  sqlite3_stmt *iterate_tickets;
+
+  /**
+   * Precompiled SQL to get ticket attributes.
+   */
+  sqlite3_stmt *get_ticket_attrs;
+  
+  /**
+   * Precompiled SQL to iterate tickets by audience.
+   */
+  sqlite3_stmt *iterate_tickets_by_audience;
+};
+
+
+/**
+ * @brief Prepare a SQL statement
+ *
+ * @param dbh handle to the database
+ * @param zSql SQL statement, UTF-8 encoded
+ * @param ppStmt set to the prepared statement
+ * @return 0 on success
+ */
+static int
+sq_prepare (sqlite3 *dbh,
+            const char *zSql,
+            sqlite3_stmt **ppStmt)
+{
+  char *dummy;
+  int result;
+
+  result =
+      sqlite3_prepare_v2 (dbh,
+                          zSql,
+                          strlen (zSql),
+                          ppStmt,
+                          (const char **) &dummy);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Prepared `%s' / %p: %d\n",
+       zSql,
+       *ppStmt,
+       result);
+  return result;
+}
+
+/**
+ * Create our database indices.
+ *
+ * @param dbh handle to the database
+ */
+static void
+create_indices (sqlite3 * dbh)
+{
+  /* create indices */
+  if ( (SQLITE_OK !=
+       sqlite3_exec (dbh,
+                      "CREATE INDEX IF NOT EXISTS identity_reverse ON identity001tickets (identity,audience)",
+                     NULL, NULL, NULL)) ||
+       (SQLITE_OK !=
+       sqlite3_exec (dbh,
+                      "CREATE INDEX IF NOT EXISTS it_iter ON identity001tickets (rnd)",
+                     NULL, NULL, NULL)) )
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+        "Failed to create indices: %s\n",
+         sqlite3_errmsg (dbh));
+}
+
+
+
+#if 0
+#define CHECK(a) GNUNET_break(a)
+#define ENULL NULL
+#else
+#define ENULL &e
+#define ENULL_DEFINED 1
+#define CHECK(a) if (! (a)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); }
+#endif
+
+
+/**
+ * Initialize the database connections and associated
+ * data structures (create tables and indices
+ * as needed as well).
+ *
+ * @param plugin the plugin context (state for this module)
+ * @return #GNUNET_OK on success
+ */
+static int
+database_setup (struct Plugin *plugin)
+{
+  sqlite3_stmt *stmt;
+  char *afsdir;
+#if ENULL_DEFINED
+  char *e;
+#endif
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
+                                               "reclaim-sqlite",
+                                               "FILENAME",
+                                               &afsdir))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                              "reclaim-sqlite",
+                               "FILENAME");
+    return GNUNET_SYSERR;
+  }
+  if (GNUNET_OK !=
+      GNUNET_DISK_file_test (afsdir))
+  {
+    if (GNUNET_OK !=
+        GNUNET_DISK_directory_create_for_file (afsdir))
+    {
+      GNUNET_break (0);
+      GNUNET_free (afsdir);
+      return GNUNET_SYSERR;
+    }
+  }
+  /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
+  plugin->fn = afsdir;
+
+  /* Open database and precompile statements */
+  if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK)
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+        _("Unable to initialize SQLite: %s.\n"),
+        sqlite3_errmsg (plugin->dbh));
+    return GNUNET_SYSERR;
+  }
+  CHECK (SQLITE_OK ==
+         sqlite3_exec (plugin->dbh,
+                       "PRAGMA temp_store=MEMORY", NULL, NULL,
+                       ENULL));
+  CHECK (SQLITE_OK ==
+         sqlite3_exec (plugin->dbh,
+                       "PRAGMA synchronous=NORMAL", NULL, NULL,
+                       ENULL));
+  CHECK (SQLITE_OK ==
+         sqlite3_exec (plugin->dbh,
+                       "PRAGMA legacy_file_format=OFF", NULL, NULL,
+                       ENULL));
+  CHECK (SQLITE_OK ==
+         sqlite3_exec (plugin->dbh,
+                       "PRAGMA auto_vacuum=INCREMENTAL", NULL,
+                       NULL, ENULL));
+  CHECK (SQLITE_OK ==
+         sqlite3_exec (plugin->dbh,
+                       "PRAGMA encoding=\"UTF-8\"", NULL,
+                       NULL, ENULL));
+  CHECK (SQLITE_OK ==
+         sqlite3_exec (plugin->dbh,
+                       "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL,
+                       ENULL));
+  CHECK (SQLITE_OK ==
+         sqlite3_exec (plugin->dbh,
+                       "PRAGMA page_size=4092", NULL, NULL,
+                       ENULL));
+
+  CHECK (SQLITE_OK ==
+         sqlite3_busy_timeout (plugin->dbh,
+                               BUSY_TIMEOUT_MS));
+
+
+  /* Create table */
+  CHECK (SQLITE_OK ==
+         sq_prepare (plugin->dbh,
+                     "SELECT 1 FROM sqlite_master WHERE tbl_name = 'identity001tickets'",
+                     &stmt));
+  if ((sqlite3_step (stmt) == SQLITE_DONE) &&
+      (sqlite3_exec
+       (plugin->dbh,
+        "CREATE TABLE identity001tickets ("
+        " identity BLOB NOT NULL DEFAULT '',"
+        " audience BLOB NOT NULL DEFAULT '',"
+             " rnd INT8 NOT NULL DEFAULT '',"
+        " attributes BLOB NOT NULL DEFAULT ''"
+       ")",
+       NULL, NULL, NULL) != SQLITE_OK))
+  {
+    LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR,
+                "sqlite3_exec");
+    sqlite3_finalize (stmt);
+    return GNUNET_SYSERR;
+  }
+  sqlite3_finalize (stmt);
+
+  create_indices (plugin->dbh);
+
+  if ( (SQLITE_OK !=
+        sq_prepare (plugin->dbh,
+                    "INSERT INTO identity001tickets (identity, audience, rnd, attributes)"
+                    " VALUES (?, ?, ?, ?)",
+                    &plugin->store_ticket)) ||
+       (SQLITE_OK !=
+        sq_prepare (plugin->dbh,
+                    "DELETE FROM identity001tickets WHERE identity=? AND rnd=?",
+                    &plugin->delete_ticket)) ||
+       (SQLITE_OK !=
+        sq_prepare (plugin->dbh,
+                    "SELECT identity,audience,rnd,attributes"
+                    " FROM identity001tickets WHERE identity=? AND rnd=?",
+                    &plugin->get_ticket_attrs)) ||
+       (SQLITE_OK !=
+        sq_prepare (plugin->dbh,
+                    "SELECT identity,audience,rnd,attributes"
+                    " FROM identity001tickets WHERE identity=?"
+                    " ORDER BY rnd LIMIT 1 OFFSET ?",
+                    &plugin->iterate_tickets)) ||
+       (SQLITE_OK !=
+        sq_prepare (plugin->dbh,
+                    "SELECT identity,audience,rnd,attributes"
+                    " FROM identity001tickets WHERE audience=?"
+                    " ORDER BY rnd LIMIT 1 OFFSET ?",
+                    &plugin->iterate_tickets_by_audience)) ) 
+  {
+    LOG_SQLITE (plugin,
+                GNUNET_ERROR_TYPE_ERROR,
+                "precompiling");
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Shutdown database connection and associate data
+ * structures.
+ * @param plugin the plugin context (state for this module)
+ */
+static void
+database_shutdown (struct Plugin *plugin)
+{
+  int result;
+  sqlite3_stmt *stmt;
+
+  if (NULL != plugin->store_ticket)
+    sqlite3_finalize (plugin->store_ticket);
+  if (NULL != plugin->delete_ticket)
+    sqlite3_finalize (plugin->delete_ticket);
+  if (NULL != plugin->iterate_tickets)
+    sqlite3_finalize (plugin->iterate_tickets);
+  if (NULL != plugin->iterate_tickets_by_audience)
+    sqlite3_finalize (plugin->iterate_tickets_by_audience);
+  if (NULL != plugin->get_ticket_attrs)
+    sqlite3_finalize (plugin->get_ticket_attrs);
+  result = sqlite3_close (plugin->dbh);
+  if (result == SQLITE_BUSY)
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+        _("Tried to close sqlite without finalizing all prepared statements.\n"));
+    stmt = sqlite3_next_stmt (plugin->dbh,
+                              NULL);
+    while (NULL != stmt)
+    {
+      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+                       "sqlite",
+                       "Closing statement %p\n",
+                       stmt);
+      result = sqlite3_finalize (stmt);
+      if (result != SQLITE_OK)
+        GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
+                         "sqlite",
+                         "Failed to close statement %p: %d\n",
+                         stmt,
+                         result);
+      stmt = sqlite3_next_stmt (plugin->dbh,
+                                NULL);
+    }
+    result = sqlite3_close (plugin->dbh);
+  }
+  if (SQLITE_OK != result)
+    LOG_SQLITE (plugin,
+                GNUNET_ERROR_TYPE_ERROR,
+                "sqlite3_close");
+
+  GNUNET_free_non_null (plugin->fn);
+}
+
+
+/**
+ * Store a ticket in the database.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param ticket the ticket to persist
+ * @param attrs the attributes associated with the ticket
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+static int
+reclaim_sqlite_store_ticket (void *cls,
+                                       const struct GNUNET_RECLAIM_Ticket *ticket,
+                                       const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
+{
+  struct Plugin *plugin = cls;
+  size_t attrs_len;
+  char *attrs_ser;
+  int n;
+
+  { 
+    /* First delete duplicates */
+    struct GNUNET_SQ_QueryParam dparams[] = {
+      GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
+      GNUNET_SQ_query_param_uint64 (&ticket->rnd),
+      GNUNET_SQ_query_param_end
+    };
+    if (GNUNET_OK !=
+        GNUNET_SQ_bind (plugin->delete_ticket,
+                        dparams))
+    {
+      LOG_SQLITE (plugin,
+                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                  "sqlite3_bind_XXXX");
+      GNUNET_SQ_reset (plugin->dbh,
+                       plugin->delete_ticket);
+      return GNUNET_SYSERR;
+    }
+    n = sqlite3_step (plugin->delete_ticket);
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->delete_ticket);
+    
+    attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
+    attrs_ser = GNUNET_malloc (attrs_len);
+    GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs,
+                              attrs_ser);
+    struct GNUNET_SQ_QueryParam sparams[] = {
+      GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
+      GNUNET_SQ_query_param_auto_from_type (&ticket->audience),
+      GNUNET_SQ_query_param_uint64 (&ticket->rnd),
+      GNUNET_SQ_query_param_fixed_size (attrs_ser, attrs_len),
+      GNUNET_SQ_query_param_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_SQ_bind (plugin->store_ticket,
+                        sparams))
+    {
+      LOG_SQLITE (plugin,
+                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                  "sqlite3_bind_XXXX");
+      GNUNET_SQ_reset (plugin->dbh,
+                       plugin->store_ticket);
+      return GNUNET_SYSERR;
+    }
+    n = sqlite3_step (plugin->store_ticket);
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->store_ticket);
+    GNUNET_free (attrs_ser);
+  }
+  switch (n)
+  {
+    case SQLITE_DONE:
+      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+                       "sqlite",
+                       "Ticket stored\n");
+      return GNUNET_OK;
+    case SQLITE_BUSY:
+      LOG_SQLITE (plugin,
+                  GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
+                  "sqlite3_step");
+      return GNUNET_NO;
+    default:
+      LOG_SQLITE (plugin,
+                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                  "sqlite3_step");
+      return GNUNET_SYSERR;
+  }
+}
+
+
+/**
+ * Store a ticket in the database.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param ticket the ticket to delete
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+static int
+reclaim_sqlite_delete_ticket (void *cls,
+                                        const struct GNUNET_RECLAIM_Ticket *ticket)
+{
+  struct Plugin *plugin = cls;
+  int n;
+
+  {  
+    struct GNUNET_SQ_QueryParam sparams[] = {
+      GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
+      GNUNET_SQ_query_param_uint64 (&ticket->rnd),
+      GNUNET_SQ_query_param_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_SQ_bind (plugin->delete_ticket,
+                        sparams))
+    {
+      LOG_SQLITE (plugin,
+                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                  "sqlite3_bind_XXXX");
+      GNUNET_SQ_reset (plugin->dbh,
+                       plugin->store_ticket);
+      return GNUNET_SYSERR;
+    }
+    n = sqlite3_step (plugin->delete_ticket);
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->delete_ticket);
+  }
+  switch (n)
+  {
+    case SQLITE_DONE:
+      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+                       "sqlite",
+                       "Ticket deleted\n");
+      return GNUNET_OK;
+    case SQLITE_BUSY:
+      LOG_SQLITE (plugin,
+                  GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
+                  "sqlite3_step");
+      return GNUNET_NO;
+    default:
+      LOG_SQLITE (plugin,
+                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                  "sqlite3_step");
+      return GNUNET_SYSERR;
+  }
+}
+
+
+/**
+ * The given 'sqlite' statement has been prepared to be run.
+ * It will return a record which should be given to the iterator.
+ * Runs the statement and parses the returned record.
+ *
+ * @param plugin plugin context
+ * @param stmt to run (and then clean up)
+ * @param iter iterator to call with the result
+ * @param iter_cls closure for @a iter
+ * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
+ */
+static int
+get_ticket_and_call_iterator (struct Plugin *plugin,
+                              sqlite3_stmt *stmt,
+                              GNUNET_RECLAIM_TicketIterator iter,
+                              void *iter_cls)
+{
+  struct GNUNET_RECLAIM_Ticket ticket;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
+  int ret;
+  int sret;
+  size_t attrs_len;
+  char *attrs_ser;
+
+  ret = GNUNET_NO;
+  if (SQLITE_ROW == (sret = sqlite3_step (stmt)))
+  {
+    struct GNUNET_SQ_ResultSpec rs[] = {
+      GNUNET_SQ_result_spec_auto_from_type (&ticket.identity),
+      GNUNET_SQ_result_spec_auto_from_type (&ticket.audience),
+      GNUNET_SQ_result_spec_uint64 (&ticket.rnd),
+      GNUNET_SQ_result_spec_variable_size ((void**)&attrs_ser,
+                                           &attrs_len),
+      GNUNET_SQ_result_spec_end
+
+    };
+    ret = GNUNET_SQ_extract_result (stmt,
+                                    rs);
+    if (GNUNET_OK != ret)
+    {
+      GNUNET_break (0);
+      ret = GNUNET_SYSERR;
+    }
+    else
+    {
+      attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (attrs_ser,
+                                          attrs_len);
+      if (NULL != iter)
+        iter (iter_cls,
+              &ticket,
+              attrs);
+      GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
+      ret = GNUNET_YES;
+    }
+    GNUNET_SQ_cleanup_result (rs);
+  }
+  else
+  {
+    if (SQLITE_DONE != sret)
+      LOG_SQLITE (plugin,
+                  GNUNET_ERROR_TYPE_ERROR,
+                  "sqlite_step");
+  }
+  GNUNET_SQ_reset (plugin->dbh,
+                   stmt);
+  return ret;
+}
+
+
+/**
+ * Lookup tickets in the datastore.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param ticket the ticket to retrieve attributes for
+ * @param iter function to call with the result
+ * @param iter_cls closure for @a iter
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+static int
+reclaim_sqlite_ticket_get_attrs (void *cls,
+                                           const struct GNUNET_RECLAIM_Ticket *ticket,
+                                           GNUNET_RECLAIM_TicketIterator iter,
+                                           void *iter_cls)
+{
+  struct Plugin *plugin = cls;
+  struct GNUNET_SQ_QueryParam params[] = {
+    GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
+    GNUNET_SQ_query_param_uint64 (&ticket->rnd),
+    GNUNET_SQ_query_param_end
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_SQ_bind (plugin->get_ticket_attrs,
+                      params))
+  {
+    LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                "sqlite3_bind_XXXX");
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->get_ticket_attrs);
+    return GNUNET_SYSERR;
+  }
+  return get_ticket_and_call_iterator (plugin,
+                                       plugin->get_ticket_attrs,
+                                       iter,
+                                       iter_cls);
+}
+
+
+/**
+ * Iterate over the results for a particular key and zone in the
+ * datastore.  Will return at most one result to the iterator.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param identity the issuing identity or audience (depending on audience switch)
+ * @param audience GNUNET_YES if identity is audience
+ * @param offset offset in the list of all matching records
+ * @param iter function to call with the result
+ * @param iter_cls closure for @a iter
+ * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
+ */
+static int
+reclaim_sqlite_iterate_tickets (void *cls,
+                                          const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+                                          int audience,
+                                          uint64_t offset,
+                                          GNUNET_RECLAIM_TicketIterator iter,
+                                          void *iter_cls)
+{
+  struct Plugin *plugin = cls;
+  sqlite3_stmt *stmt;
+  int err;
+
+  if (NULL == identity)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  struct GNUNET_SQ_QueryParam params[] = {
+    GNUNET_SQ_query_param_auto_from_type (identity),
+    GNUNET_SQ_query_param_uint64 (&offset),
+    GNUNET_SQ_query_param_end
+  };
+  if (GNUNET_YES == audience)
+  {
+    stmt = plugin->iterate_tickets_by_audience;
+    err = GNUNET_SQ_bind (stmt,
+                          params);
+  }
+  else
+  {
+    stmt = plugin->iterate_tickets;
+    err = GNUNET_SQ_bind (stmt,
+                          params);
+  }
+  if (GNUNET_OK != err)
+  {
+    LOG_SQLITE (plugin,
+                GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                "sqlite3_bind_XXXX");
+    GNUNET_SQ_reset (plugin->dbh,
+                     stmt);
+    return GNUNET_SYSERR;
+  }
+  return get_ticket_and_call_iterator (plugin,
+                                       stmt,
+                                       iter,
+                                       iter_cls);
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls the "struct GNUNET_RECLAIM_PluginEnvironment*"
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_reclaim_sqlite_init (void *cls)
+{
+  static struct Plugin plugin;
+  const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+  struct GNUNET_RECLAIM_PluginFunctions *api;
+
+  if (NULL != plugin.cfg)
+    return NULL;                /* can only initialize once! */
+  memset (&plugin, 0, sizeof (struct Plugin));
+  plugin.cfg = cfg;
+  if (GNUNET_OK != database_setup (&plugin))
+  {
+    database_shutdown (&plugin);
+    return NULL;
+  }
+  api = GNUNET_new (struct GNUNET_RECLAIM_PluginFunctions);
+  api->cls = &plugin;
+  api->store_ticket = &reclaim_sqlite_store_ticket;
+  api->delete_ticket = &reclaim_sqlite_delete_ticket;
+  api->iterate_tickets = &reclaim_sqlite_iterate_tickets;
+  api->get_ticket_attributes = &reclaim_sqlite_ticket_get_attrs;
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       _("Sqlite database running\n"));
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_reclaim_sqlite_done (void *cls)
+{
+  struct GNUNET_RECLAIM_PluginFunctions *api = cls;
+  struct Plugin *plugin = api->cls;
+
+  database_shutdown (plugin);
+  plugin->cfg = NULL;
+  GNUNET_free (api);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "sqlite plugin is finished\n");
+  return NULL;
+}
+
+/* end of plugin_reclaim_sqlite.c */
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c
new file mode 100644 (file)
index 0000000..abb3f59
--- /dev/null
@@ -0,0 +1,2227 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+  
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @author Philippe Buschmann
+ * @file identity/plugin_rest_openid_connect.c
+ * @brief GNUnet Namestore REST plugin
+ *
+ */
+
+#include "platform.h"
+#include "gnunet_rest_plugin.h"
+#include "gnunet_identity_service.h"
+#include "gnunet_gns_service.h"
+#include "gnunet_gnsrecord_lib.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_rest_lib.h"
+#include "gnunet_jsonapi_lib.h"
+#include "gnunet_jsonapi_util.h"
+#include "microhttpd.h"
+#include <jansson.h>
+#include <inttypes.h>
+#include "gnunet_signatures.h"
+#include "gnunet_reclaim_attribute_lib.h"
+#include "gnunet_reclaim_service.h"
+#include "jwt.h"
+
+/**
+ * REST root namespace
+ */
+#define GNUNET_REST_API_NS_OIDC "/openid"
+
+/**
+ * Authorize endpoint
+ */
+#define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize"
+
+/**
+ * Token endpoint
+ */
+#define GNUNET_REST_API_NS_TOKEN "/openid/token"
+
+/**
+ * UserInfo endpoint
+ */
+#define GNUNET_REST_API_NS_USERINFO "/openid/userinfo"
+
+/**
+ * Login namespace
+ */
+#define GNUNET_REST_API_NS_LOGIN "/openid/login"
+
+/**
+ * Attribute key
+ */
+#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE "attribute"
+
+/**
+ * Ticket key
+ */
+#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket"
+
+
+/**
+ * Value key
+ */
+#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE_VALUE "value"
+
+/**
+ * State while collecting all egos
+ */
+#define ID_REST_STATE_INIT 0
+
+/**
+ * Done collecting egos
+ */
+#define ID_REST_STATE_POST_INIT 1
+
+/**
+ * OIDC grant_type key
+ */
+#define OIDC_GRANT_TYPE_KEY "grant_type"
+
+/**
+ * OIDC grant_type key
+ */
+#define OIDC_GRANT_TYPE_VALUE "authorization_code"
+
+/**
+ * OIDC code key
+ */
+#define OIDC_CODE_KEY "code"
+
+/**
+ * OIDC response_type key
+ */
+#define OIDC_RESPONSE_TYPE_KEY "response_type"
+
+/**
+ * OIDC client_id key
+ */
+#define OIDC_CLIENT_ID_KEY "client_id"
+
+/**
+ * OIDC scope key
+ */
+#define OIDC_SCOPE_KEY "scope"
+
+/**
+ * OIDC redirect_uri key
+ */
+#define OIDC_REDIRECT_URI_KEY "redirect_uri"
+
+/**
+ * OIDC state key
+ */
+#define OIDC_STATE_KEY "state"
+
+/**
+ * OIDC nonce key
+ */
+#define OIDC_NONCE_KEY "nonce"
+
+/**
+ * OIDC cookie header key
+ */
+#define OIDC_COOKIE_HEADER_KEY "cookie"
+
+/**
+ * OIDC cookie header information key
+ */
+#define OIDC_AUTHORIZATION_HEADER_KEY "authorization"
+
+/**
+ * OIDC cookie header information key
+ */
+#define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity="
+
+/**
+ * OIDC expected response_type while authorizing
+ */
+#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code"
+
+/**
+ * OIDC expected scope part while authorizing
+ */
+#define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid"
+
+/**
+ * OIDC ignored parameter array
+ */
+static char* OIDC_ignored_parameter_array [] =
+{
+  "display",
+  "prompt",
+  "max_age",
+  "ui_locales", 
+  "response_mode",
+  "id_token_hint",
+  "login_hint", 
+  "acr_values"
+};
+
+/**
+ * OIDC authorized identities and times hashmap
+ */
+struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_login_time;
+
+/**
+ * OIDC authorized identities and times hashmap
+ */
+struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_grants;
+
+/**
+ * OIDC ticket/code use only once
+ */
+struct GNUNET_CONTAINER_MultiHashMap *OIDC_ticket_once;
+
+/**
+ * OIDC access_token to ticket and ego
+ */
+struct GNUNET_CONTAINER_MultiHashMap *OIDC_interpret_access_token;
+
+/**
+ * The configuration handle
+ */
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * HTTP methods allows for this plugin
+ */
+static char* allow_methods;
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct Plugin
+{
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+};
+
+/**
+ * OIDC needed variables
+ */
+struct OIDC_Variables
+{
+  /**
+   * The RP client public key
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey client_pkey;
+
+  /**
+   * The OIDC client id of the RP
+   */
+  char *client_id;
+
+  /**
+   * GNUNET_YES if there is a delegation to 
+   * this RP or if it is a local identity
+   */
+  int is_client_trusted;
+
+  /**
+   * The OIDC redirect uri
+   */
+  char *redirect_uri;
+
+  /**
+   * The list of oidc scopes
+   */
+  char *scope;
+
+  /**
+   * The OIDC state
+   */
+  char *state;
+
+  /**
+   * The OIDC nonce
+   */
+  char *nonce;
+
+  /**
+   * The OIDC response type
+   */
+  char *response_type;
+
+  /**
+   * The identity chosen by the user to login
+   */
+  char *login_identity;
+
+  /**
+   * The response JSON
+   */
+  json_t *response;
+
+};
+
+/**
+ * The ego list
+ */
+struct EgoEntry
+{
+  /**
+   * DLL
+   */
+  struct EgoEntry *next;
+
+  /**
+   * DLL
+   */
+  struct EgoEntry *prev;
+
+  /**
+   * Ego Identifier
+   */
+  char *identifier;
+
+  /**
+   * Public key string
+   */
+  char *keystring;
+
+  /**
+   * The Ego
+   */
+  struct GNUNET_IDENTITY_Ego *ego;
+};
+
+
+struct RequestHandle
+{
+  /**
+   * Ego list
+   */
+  struct EgoEntry *ego_head;
+
+  /**
+   * Ego list
+   */
+  struct EgoEntry *ego_tail;
+
+  /**
+   * Selected ego
+   */
+  struct EgoEntry *ego_entry;
+
+  /**
+   * Pointer to ego private key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
+
+  /**
+   * OIDC variables
+   */
+  struct OIDC_Variables *oidc;
+
+  /**
+   * The processing state
+   */
+  int state;
+
+  /**
+   * Handle to Identity service.
+   */
+  struct GNUNET_IDENTITY_Handle *identity_handle;
+
+  /**
+   * Rest connection
+   */
+  struct GNUNET_REST_RequestHandle *rest_handle;
+
+  /**
+   * Handle to NAMESTORE
+   */
+  struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+  /**
+   * Iterator for NAMESTORE
+   */
+  struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it;
+
+  /**
+   * Attribute claim list
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list;
+
+  /**
+   * IDENTITY Operation
+   */
+  struct GNUNET_IDENTITY_Operation *op;
+
+  /**
+   * Identity Provider
+   */
+  struct GNUNET_RECLAIM_Handle *idp;
+
+  /**
+   * Idp Operation
+   */
+  struct GNUNET_RECLAIM_Operation *idp_op;
+
+  /**
+   * Attribute iterator
+   */
+  struct GNUNET_RECLAIM_AttributeIterator *attr_it;
+
+  /**
+   * Ticket iterator
+   */
+  struct GNUNET_RECLAIM_TicketIterator *ticket_it;
+
+  /**
+   * A ticket
+   */
+  struct GNUNET_RECLAIM_Ticket ticket;
+
+  /**
+   * Desired timeout for the lookup (default is no timeout).
+   */
+  struct GNUNET_TIME_Relative timeout;
+
+  /**
+   * ID of a task associated with the resolution process.
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * The plugin result processor
+   */
+  GNUNET_REST_ResultProcessor proc;
+
+  /**
+   * The closure of the result processor
+   */
+  void *proc_cls;
+
+  /**
+   * The url
+   */
+  char *url;
+
+  /**
+   * The tld for redirect
+   */
+  char *tld;
+
+  /**
+   * Error response message
+   */
+  char *emsg;
+
+  /**
+   * Error response description
+   */
+  char *edesc;
+
+  /**
+   * Reponse code
+   */
+  int response_code;
+
+  /**
+   * Response object
+   */
+  struct GNUNET_JSONAPI_Document *resp_object;
+
+};
+
+/**
+ * Cleanup lookup handle
+ * @param handle Handle to clean up
+ */
+static void
+cleanup_handle (struct RequestHandle *handle)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_entry;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_tmp;
+  struct EgoEntry *ego_entry;
+  struct EgoEntry *ego_tmp;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up\n");
+  if (NULL != handle->resp_object)
+    GNUNET_JSONAPI_document_delete (handle->resp_object);
+  if (NULL != handle->timeout_task)
+    GNUNET_SCHEDULER_cancel (handle->timeout_task);
+  if (NULL != handle->identity_handle)
+    GNUNET_IDENTITY_disconnect (handle->identity_handle);
+  if (NULL != handle->attr_it)
+    GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
+  if (NULL != handle->ticket_it)
+    GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
+  if (NULL != handle->idp)
+    GNUNET_RECLAIM_disconnect (handle->idp);
+  if (NULL != handle->url)
+    GNUNET_free (handle->url);
+  if (NULL != handle->tld)
+    GNUNET_free (handle->tld);
+  if (NULL != handle->emsg)
+    GNUNET_free (handle->emsg);
+  if (NULL != handle->edesc)
+    GNUNET_free (handle->edesc);
+  if (NULL != handle->namestore_handle)
+    GNUNET_NAMESTORE_disconnect (handle->namestore_handle);
+  if (NULL != handle->oidc)
+  {
+    if (NULL != handle->oidc->client_id)
+      GNUNET_free(handle->oidc->client_id);
+    if (NULL != handle->oidc->login_identity)
+      GNUNET_free(handle->oidc->login_identity);
+    if (NULL != handle->oidc->nonce)
+      GNUNET_free(handle->oidc->nonce);
+    if (NULL != handle->oidc->redirect_uri)
+      GNUNET_free(handle->oidc->redirect_uri);
+    if (NULL != handle->oidc->response_type)
+      GNUNET_free(handle->oidc->response_type);
+    if (NULL != handle->oidc->scope)
+      GNUNET_free(handle->oidc->scope);
+    if (NULL != handle->oidc->state)
+      GNUNET_free(handle->oidc->state);
+    if (NULL != handle->oidc->response)
+      json_decref(handle->oidc->response);
+    GNUNET_free(handle->oidc);
+  }
+  if ( NULL != handle->attr_list )
+  {
+    for (claim_entry = handle->attr_list->list_head;
+         NULL != claim_entry;)
+    {
+      claim_tmp = claim_entry;
+      claim_entry = claim_entry->next;
+      GNUNET_free(claim_tmp->claim);
+      GNUNET_free(claim_tmp);
+    }
+    GNUNET_free (handle->attr_list);
+  }
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;)
+  {
+    ego_tmp = ego_entry;
+    ego_entry = ego_entry->next;
+    GNUNET_free (ego_tmp->identifier);
+    GNUNET_free (ego_tmp->keystring);
+    GNUNET_free (ego_tmp);
+  }
+  if (NULL != handle->attr_it)
+  {
+    GNUNET_free(handle->attr_it);
+  }
+  GNUNET_free (handle);
+}
+
+static void
+cleanup_handle_delayed (void *cls)
+{
+  cleanup_handle (cls);
+}
+
+
+/**
+ * Task run on error, sends error message.  Cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  char *json_error;
+
+  GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
+                   handle->emsg,
+                   (NULL != handle->edesc) ? handle->edesc : "",
+                   (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
+                   (NULL != handle->oidc->state) ? handle->oidc->state : "",
+                   (NULL != handle->oidc->state) ? "\"" : "");
+  if ( 0 == handle->response_code )
+  {
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+  }
+  resp = GNUNET_REST_create_response (json_error);
+  if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
+  {
+    MHD_add_response_header(resp, "WWW-Authenticate", "Basic");
+  }
+  MHD_add_response_header (resp, "Content-Type", "application/json");
+  handle->proc (handle->proc_cls, resp, handle->response_code);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  GNUNET_free (json_error);
+}
+
+
+/**
+ * Task run on error in userinfo endpoint, sends error header. Cleans up
+ * everything
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_userinfo_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  char *error;
+
+  GNUNET_asprintf (&error, "error=\"%s\", error_description=\"%s\"",
+                   handle->emsg,
+                   (NULL != handle->edesc) ? handle->edesc : "");
+  resp = GNUNET_REST_create_response ("");
+  MHD_add_response_header(resp, "WWW-Authenticate", error);
+  handle->proc (handle->proc_cls, resp, handle->response_code);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  GNUNET_free (error);
+}
+
+
+/**
+ * Task run on error, sends error message and redirects. Cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_redirect_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  char* redirect;
+  GNUNET_asprintf (&redirect,
+                   "%s?error=%s&error_description=%s%s%s",
+                   handle->oidc->redirect_uri, handle->emsg, handle->edesc,
+                   (NULL != handle->oidc->state) ? "&state=" : "",
+                   (NULL != handle->oidc->state) ? handle->oidc->state : "");
+  resp = GNUNET_REST_create_response ("");
+  MHD_add_response_header (resp, "Location", redirect);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  GNUNET_free (redirect);
+}
+
+/**
+ * Task run on timeout, sends error message.  Cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_timeout (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  handle->timeout_task = NULL;
+  do_error (handle);
+}
+
+/**
+ * Return attributes for claim
+ *
+ * @param cls the request handle
+ */
+static void
+return_userinfo_response (void *cls)
+{
+  char* result_str;
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+
+  result_str = json_dumps (handle->oidc->response, 0);
+
+  resp = GNUNET_REST_create_response (result_str);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_free (result_str);
+  cleanup_handle (handle);
+}
+
+/**
+ * Returns base64 encoded string without padding
+ *
+ * @param string the string to encode
+ * @return base64 encoded string
+ */
+static char*
+base_64_encode(const char *s)
+{
+  char *enc;
+  char *tmp;
+
+  GNUNET_STRINGS_base64_encode(s, strlen(s), &enc);
+  tmp = strrchr (enc, '=');
+  *tmp = '\0';
+  return enc;
+}
+
+/**
+ * Respond to OPTIONS request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+options_cont (struct GNUNET_REST_RequestHandle *con_handle,
+              const char* url,
+              void *cls)
+{
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  //For now, independent of path return all options
+  resp = GNUNET_REST_create_response (NULL);
+  MHD_add_response_header (resp,
+                           "Access-Control-Allow-Methods",
+                           allow_methods);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  cleanup_handle (handle);
+  return;
+}
+
+/**
+ * Interprets cookie header and pass its identity keystring to handle
+ */
+static void
+cookie_identity_interpretation (struct RequestHandle *handle)
+{
+  struct GNUNET_HashCode cache_key;
+  char *cookies;
+  struct GNUNET_TIME_Absolute current_time, *relog_time;
+  char delimiter[] = "; ";
+
+  //gets identity of login try with cookie
+  GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY, strlen (OIDC_COOKIE_HEADER_KEY),
+                      &cache_key);
+  if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map,
+                                                             &cache_key) )
+  {
+    //splits cookies and find 'Identity' cookie
+    cookies = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key);
+    handle->oidc->login_identity = strtok(cookies, delimiter);
+
+    while ( NULL != handle->oidc->login_identity )
+    {
+      if ( NULL != strstr (handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY) )
+      {
+        break;
+      }
+      handle->oidc->login_identity = strtok (NULL, delimiter);
+    }
+    GNUNET_CRYPTO_hash (handle->oidc->login_identity, strlen (handle->oidc->login_identity),
+                        &cache_key);
+    if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time, &cache_key) )
+    {
+      relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time,
+                                                      &cache_key);
+      current_time = GNUNET_TIME_absolute_get ();
+      // 30 min after old login -> redirect to login
+      if ( current_time.abs_value_us <= relog_time->abs_value_us )
+      {
+        handle->oidc->login_identity = strtok(handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY);
+        handle->oidc->login_identity = GNUNET_strdup(handle->oidc->login_identity);
+      } else {
+        handle->oidc->login_identity = NULL;
+      }
+    }
+    else
+    {
+      handle->oidc->login_identity = NULL;
+    }
+  }
+}
+
+/**
+ * Redirects to login page stored in configuration file
+ */
+static void
+login_redirection(void *cls)
+{
+  char *login_base_url;
+  char *new_redirect;
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  if ( GNUNET_OK
+       == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin",
+                                                 "address", &login_base_url) )
+  {
+    GNUNET_asprintf (&new_redirect, "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s",
+                     login_base_url,
+                     OIDC_RESPONSE_TYPE_KEY,
+                     handle->oidc->response_type,
+                     OIDC_CLIENT_ID_KEY,
+                     handle->oidc->client_id,
+                     OIDC_REDIRECT_URI_KEY,
+                     handle->oidc->redirect_uri,
+                     OIDC_SCOPE_KEY,
+                     handle->oidc->scope,
+                     OIDC_STATE_KEY,
+                     (NULL != handle->oidc->state) ? handle->oidc->state : "",
+                     OIDC_NONCE_KEY,
+                     (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "");
+    resp = GNUNET_REST_create_response ("");
+    MHD_add_response_header (resp, "Location", new_redirect);
+    GNUNET_free(login_base_url);
+  }
+  else
+  {
+    handle->emsg = GNUNET_strdup("server_error");
+    handle->edesc = GNUNET_strdup ("gnunet configuration failed");
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
+  GNUNET_free(new_redirect);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+}
+
+/**
+ * Does internal server error when iteration failed.
+ */
+static void
+oidc_iteration_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  handle->emsg = GNUNET_strdup("INTERNAL_SERVER_ERROR");
+  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+  GNUNET_SCHEDULER_add_now (&do_error, handle);
+}
+
+static void get_client_name_result (void *cls,
+                                    const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                                    const char *label,
+                                    unsigned int rd_count,
+                                    const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  char *ticket_str;
+  char *redirect_uri;
+  char *code_json_string;
+  char *code_base64_final_string;
+  char *redirect_path;
+  char *tmp;
+  char *tmp_prefix;
+  char *prefix;
+  ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket,
+                                                    sizeof (struct GNUNET_RECLAIM_Ticket));
+  //TODO change if more attributes are needed (see max_age)
+  GNUNET_asprintf (&code_json_string, "{\"ticket\":\"%s\"%s%s%s}",
+                   ticket_str,
+                   (NULL != handle->oidc->nonce) ? ", \"nonce\":\"" : "",
+                   (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "",
+                   (NULL != handle->oidc->nonce) ? "\"" : "");
+  code_base64_final_string = base_64_encode(code_json_string);
+  tmp = GNUNET_strdup (handle->oidc->redirect_uri);
+  redirect_path = strtok (tmp, "/");
+  redirect_path = strtok (NULL, "/");
+  redirect_path = strtok (NULL, "/");
+  tmp_prefix = GNUNET_strdup (handle->oidc->redirect_uri);
+  prefix = strrchr (tmp_prefix,
+                    (unsigned char) '.');
+  *prefix = '\0';
+  GNUNET_asprintf (&redirect_uri, "%s.%s/%s?%s=%s&state=%s",
+                   tmp_prefix,
+                   handle->tld,
+                   redirect_path,
+                   handle->oidc->response_type,
+                   code_base64_final_string, handle->oidc->state);
+  resp = GNUNET_REST_create_response ("");
+  MHD_add_response_header (resp, "Location", redirect_uri);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  GNUNET_free (tmp);
+  GNUNET_free (tmp_prefix);
+  GNUNET_free (redirect_uri);
+  GNUNET_free (ticket_str);
+  GNUNET_free (code_json_string);
+  GNUNET_free (code_base64_final_string);
+  return;
+}
+
+static void
+get_client_name_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  handle->emsg = GNUNET_strdup("server_error");
+  handle->edesc = GNUNET_strdup("Server cannot generate ticket, no name found for client.");
+  GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+}
+
+/**
+ * Issues ticket and redirects to relying party with the authorization code as
+ * parameter. Otherwise redirects with error
+ */
+static void
+oidc_ticket_issue_cb (void* cls,
+                      const struct GNUNET_RECLAIM_Ticket *ticket)
+{
+  struct RequestHandle *handle = cls;
+  handle->idp_op = NULL;
+  handle->ticket = *ticket;
+  if (NULL != ticket) {
+    GNUNET_NAMESTORE_zone_to_name (handle->namestore_handle,
+                                   &handle->priv_key,
+                                   &handle->oidc->client_pkey,
+                                   &get_client_name_error,
+                                   handle,
+                                   &get_client_name_result,
+                                   handle);
+    return;
+  }
+  handle->emsg = GNUNET_strdup("server_error");
+  handle->edesc = GNUNET_strdup("Server cannot generate ticket.");
+  GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+}
+
+static void
+oidc_collect_finished_cb (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  handle->attr_it = NULL;
+  handle->ticket_it = NULL;
+  if (NULL == handle->attr_list->list_head)
+  {
+    handle->emsg = GNUNET_strdup("invalid_scope");
+    handle->edesc = GNUNET_strdup("The requested scope is not available.");
+    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+    return;
+  }
+  handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp,
+                                                          &handle->priv_key,
+                                                          &handle->oidc->client_pkey,
+                                                          handle->attr_list,
+                                                          &oidc_ticket_issue_cb,
+                                                          handle);
+}
+
+
+/**
+ * Collects all attributes for an ego if in scope parameter
+ */
+static void
+oidc_attr_collect (void *cls,
+                   const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+                   const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  char* scope_variables;
+  char* scope_variable;
+  char delimiter[]=" ";
+
+  if ( (NULL == attr->name) || (NULL == attr->data) )
+  {
+    GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+    return;
+  }
+
+  scope_variables = GNUNET_strdup(handle->oidc->scope);
+  scope_variable = strtok (scope_variables, delimiter);
+  while (NULL != scope_variable)
+  {
+    if ( 0 == strcmp (attr->name, scope_variable) )
+    {
+      break;
+    }
+    scope_variable = strtok (NULL, delimiter);
+  }
+  if ( NULL == scope_variable )
+  {
+    GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+    GNUNET_free(scope_variables);
+    return;
+  }
+  GNUNET_free(scope_variables);
+
+  le = GNUNET_new(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+  le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name, attr->type,
+                                                   attr->data, attr->data_size);
+  GNUNET_CONTAINER_DLL_insert(handle->attr_list->list_head,
+                              handle->attr_list->list_tail, le);
+  GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+}
+
+
+/**
+ * Checks time and cookie and redirects accordingly
+ */
+static void
+login_check (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_TIME_Absolute current_time, *relog_time;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pubkey, ego_pkey;
+  struct GNUNET_HashCode cache_key;
+  char *identity_cookie;
+
+  GNUNET_asprintf (&identity_cookie, "Identity=%s", handle->oidc->login_identity);
+  GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
+  GNUNET_free(identity_cookie);
+  //No login time for identity -> redirect to login
+  if ( GNUNET_YES
+       == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time,
+                                                  &cache_key) )
+  {
+    relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time,
+                                                    &cache_key);
+    current_time = GNUNET_TIME_absolute_get ();
+    // 30 min after old login -> redirect to login
+    if ( current_time.abs_value_us <= relog_time->abs_value_us )
+    {
+      if ( GNUNET_OK
+           != GNUNET_CRYPTO_ecdsa_public_key_from_string (
+                                                          handle->oidc->login_identity,
+                                                          strlen (handle->oidc->login_identity), &pubkey) )
+      {
+        handle->emsg = GNUNET_strdup("invalid_cookie");
+        handle->edesc = GNUNET_strdup(
+                                      "The cookie of a login identity is not valid");
+        GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+        return;
+      }
+      // iterate over egos and compare their public key
+      for (handle->ego_entry = handle->ego_head;
+           NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next)
+      {
+        GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
+        if ( 0
+             == memcmp (&ego_pkey, &pubkey,
+                        sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
+        {
+          handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (
+                                                                   handle->ego_entry->ego);
+          handle->resp_object = GNUNET_JSONAPI_document_new ();
+          handle->idp = GNUNET_RECLAIM_connect (cfg);
+          handle->attr_list = GNUNET_new(
+                                         struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
+          handle->attr_it = GNUNET_RECLAIM_get_attributes_start (
+                                                                           handle->idp, &handle->priv_key, &oidc_iteration_error, handle,
+                                                                           &oidc_attr_collect, handle, &oidc_collect_finished_cb, handle);
+          return;
+        }
+      }
+      //handle->emsg = GNUNET_strdup("invalid_cookie");
+      //handle->edesc = GNUNET_strdup(
+      //                              "The cookie of the login identity is not valid");
+      //GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+      GNUNET_SCHEDULER_add_now (&login_redirection,handle);
+      return;
+    }
+  }
+}
+
+/**
+ * Searches for client_id in namestore. If found trust status stored in handle
+ * Else continues to search
+ *
+ * @param handle the RequestHandle
+ */
+static void
+namestore_iteration_callback (
+                              void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
+                              const char *rname, unsigned int rd_len,
+                              const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_CRYPTO_EcdsaPublicKey login_identity_pkey;
+  struct GNUNET_CRYPTO_EcdsaPublicKey current_zone_pkey;
+  int i;
+
+  for (i = 0; i < rd_len; i++)
+  {
+    if ( GNUNET_GNSRECORD_TYPE_PKEY != rd[i].record_type )
+      continue;
+
+    if ( NULL != handle->oidc->login_identity )
+    {
+      GNUNET_CRYPTO_ecdsa_public_key_from_string (
+                                                  handle->oidc->login_identity,
+                                                  strlen (handle->oidc->login_identity),
+                                                  &login_identity_pkey);
+      GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego,
+                                          &current_zone_pkey);
+
+      if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey,
+                        sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
+      {
+        if ( 0 == memcmp (&login_identity_pkey, &current_zone_pkey,
+                          sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
+        {
+          handle->oidc->is_client_trusted = GNUNET_YES;
+        }
+      }
+    }
+    else
+    {
+      if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey,
+                        sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
+      {
+        handle->oidc->is_client_trusted = GNUNET_YES;
+      }
+    }
+  }
+
+  GNUNET_NAMESTORE_zone_iterator_next (handle->namestore_handle_it,
+                                      1);
+}
+
+
+/**
+ * Iteration over all results finished, build final
+ * response.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+namestore_iteration_finished (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode cache_key;
+
+  char *expected_scope;
+  char delimiter[]=" ";
+  int number_of_ignored_parameter, iterator;
+
+
+  handle->ego_entry = handle->ego_entry->next;
+
+  if(NULL != handle->ego_entry)
+  {
+    handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego);
+    handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start (handle->namestore_handle, &handle->priv_key,
+                                                                         &oidc_iteration_error, handle, &namestore_iteration_callback, handle,
+                                                                         &namestore_iteration_finished, handle);
+    return;
+  }
+  if (GNUNET_NO == handle->oidc->is_client_trusted)
+  {
+    handle->emsg = GNUNET_strdup("unauthorized_client");
+    handle->edesc = GNUNET_strdup("The client is not authorized to request an "
+                                  "authorization code using this method.");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  // REQUIRED value: redirect_uri
+  GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY),
+                      &cache_key);
+  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                                           &cache_key))
+  {
+    handle->emsg=GNUNET_strdup("invalid_request");
+    handle->edesc=GNUNET_strdup("missing parameter redirect_uri");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->oidc->redirect_uri = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
+                                                                                &cache_key));
+
+  // REQUIRED value: response_type
+  GNUNET_CRYPTO_hash (OIDC_RESPONSE_TYPE_KEY, strlen (OIDC_RESPONSE_TYPE_KEY),
+                      &cache_key);
+  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                                           &cache_key))
+  {
+    handle->emsg=GNUNET_strdup("invalid_request");
+    handle->edesc=GNUNET_strdup("missing parameter response_type");
+    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+    return;
+  }
+  handle->oidc->response_type = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
+                                                                  &cache_key);
+  handle->oidc->response_type = GNUNET_strdup (handle->oidc->response_type);
+
+  // REQUIRED value: scope
+  GNUNET_CRYPTO_hash (OIDC_SCOPE_KEY, strlen (OIDC_SCOPE_KEY), &cache_key);
+  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                                           &cache_key))
+  {
+    handle->emsg=GNUNET_strdup("invalid_request");
+    handle->edesc=GNUNET_strdup("missing parameter scope");
+    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+    return;
+  }
+  handle->oidc->scope = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
+                                                          &cache_key);
+  handle->oidc->scope = GNUNET_strdup(handle->oidc->scope);
+
+  //OPTIONAL value: nonce
+  GNUNET_CRYPTO_hash (OIDC_NONCE_KEY, strlen (OIDC_NONCE_KEY), &cache_key);
+  if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                                            &cache_key))
+  {
+    handle->oidc->nonce = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
+                                                            &cache_key);
+    handle->oidc->nonce = GNUNET_strdup (handle->oidc->nonce);
+  }
+
+  //TODO check other values if needed
+  number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
+  for( iterator = 0; iterator < number_of_ignored_parameter; iterator++ )
+  {
+    GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator],
+                        strlen(OIDC_ignored_parameter_array[iterator]),
+                        &cache_key);
+    if(GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(handle->rest_handle->url_param_map,
+                                                            &cache_key))
+    {
+      handle->emsg=GNUNET_strdup("access_denied");
+      GNUNET_asprintf (&handle->edesc, "Server will not handle parameter: %s",
+                       OIDC_ignored_parameter_array[iterator]);
+      GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+      return;
+    }
+  }
+
+  // Checks if response_type is 'code'
+  if( 0 != strcmp( handle->oidc->response_type, OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE ) )
+  {
+    handle->emsg=GNUNET_strdup("unsupported_response_type");
+    handle->edesc=GNUNET_strdup("The authorization server does not support "
+                                "obtaining this authorization code.");
+    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+    return;
+  }
+
+  // Checks if scope contains 'openid'
+  expected_scope = GNUNET_strdup(handle->oidc->scope);
+  char* test;
+  test = strtok (expected_scope, delimiter);
+  while (NULL != test)
+  {
+    if ( 0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope) )
+    {
+      break;
+    }
+    test = strtok (NULL, delimiter);
+  }
+  if (NULL == test)
+  {
+    handle->emsg = GNUNET_strdup("invalid_scope");
+    handle->edesc=GNUNET_strdup("The requested scope is invalid, unknown, or "
+                                "malformed.");
+    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+    GNUNET_free(expected_scope);
+    return;
+  }
+
+  GNUNET_free(expected_scope);
+
+  if( NULL != handle->oidc->login_identity )
+  {
+    GNUNET_SCHEDULER_add_now(&login_check,handle);
+    return;
+  }
+
+  GNUNET_SCHEDULER_add_now(&login_redirection,handle);
+}
+
+/**
+ * Responds to authorization GET and url-encoded POST request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
+                    const char* url,
+                    void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode cache_key;
+  struct EgoEntry *tmp_ego;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+
+  cookie_identity_interpretation(handle);
+
+  //RECOMMENDED value: state - REQUIRED for answers
+  GNUNET_CRYPTO_hash (OIDC_STATE_KEY, strlen (OIDC_STATE_KEY), &cache_key);
+  if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                                            &cache_key))
+  {
+    handle->oidc->state = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
+                                                            &cache_key);
+    handle->oidc->state = GNUNET_strdup (handle->oidc->state);
+  }
+
+  // REQUIRED value: client_id
+  GNUNET_CRYPTO_hash (OIDC_CLIENT_ID_KEY, strlen (OIDC_CLIENT_ID_KEY),
+                      &cache_key);
+  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                                           &cache_key))
+  {
+    handle->emsg=GNUNET_strdup("invalid_request");
+    handle->edesc=GNUNET_strdup("missing parameter client_id");
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->oidc->client_id = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
+                                                                             &cache_key));
+
+  if ( GNUNET_OK
+       != GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->oidc->client_id,
+                                                      strlen (handle->oidc->client_id),
+                                                      &handle->oidc->client_pkey) )
+  {
+    handle->emsg = GNUNET_strdup("unauthorized_client");
+    handle->edesc = GNUNET_strdup("The client is not authorized to request an "
+                                  "authorization code using this method.");
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+
+  if ( NULL == handle->ego_head )
+  {
+    handle->emsg = GNUNET_strdup("server_error");
+    handle->edesc = GNUNET_strdup ("Egos are missing");
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  handle->ego_entry = handle->ego_head;
+  handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
+  handle->oidc->is_client_trusted = GNUNET_NO;
+
+  //First check if client_id is one of our egos; TODO: handle other TLD cases: Delegation, from config
+  for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
+  {
+    priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
+    GNUNET_CRYPTO_ecdsa_key_get_public (priv_key,
+                                        &pkey);
+    if ( 0 == memcmp (&pkey, &handle->oidc->client_pkey,
+                      sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
+    {
+      handle->tld = GNUNET_strdup (tmp_ego->identifier);
+      handle->oidc->is_client_trusted = GNUNET_YES;
+      handle->ego_entry = handle->ego_tail;
+    }
+  }
+
+
+  // Checks if client_id is valid:
+  handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start (
+                                                                       handle->namestore_handle, &handle->priv_key, &oidc_iteration_error,
+                                                                       handle, &namestore_iteration_callback, handle,
+                                                                       &namestore_iteration_finished, handle);
+}
+
+/**
+ * Combines an identity with a login time and responds OK to login request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+login_cont (struct GNUNET_REST_RequestHandle *con_handle,
+            const char* url,
+            void *cls)
+{
+  struct MHD_Response *resp = GNUNET_REST_create_response ("");
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode cache_key;
+  struct GNUNET_TIME_Absolute *current_time;
+  struct GNUNET_TIME_Absolute *last_time;
+  char* cookie;
+  json_t *root;
+  json_error_t error;
+  json_t *identity;
+  char term_data[handle->rest_handle->data_size+1];
+  term_data[handle->rest_handle->data_size] = '\0';
+  GNUNET_memcpy (term_data, handle->rest_handle->data, handle->rest_handle->data_size);
+  root = json_loads (term_data, JSON_DECODE_ANY, &error);
+  identity = json_object_get (root, "identity");
+  if ( json_is_string(identity) )
+  {
+    GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
+    MHD_add_response_header (resp, "Set-Cookie", cookie);
+    MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST");
+    GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
+
+    current_time = GNUNET_new(struct GNUNET_TIME_Absolute);
+    *current_time = GNUNET_TIME_relative_to_absolute (
+                                                      GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (),
+                                                                                     5));
+    last_time = GNUNET_CONTAINER_multihashmap_get(OIDC_identity_login_time, &cache_key);
+    if (NULL != last_time)
+    {
+      GNUNET_free(last_time);
+    }
+    GNUNET_CONTAINER_multihashmap_put (
+                                       OIDC_identity_login_time, &cache_key, current_time,
+                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+    GNUNET_free(cookie);
+  }
+  else
+  {
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
+  }
+  json_decref (root);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  return;
+}
+
+/**
+ * Responds to token url-encoded POST request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
+                const char* url,
+                void *cls)
+{
+  //TODO static strings
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode cache_key;
+  char *authorization, *credentials;
+  char delimiter[]=" ";
+  char delimiter_user_psw[]=":";
+  char *grant_type, *code;
+  char *user_psw = NULL, *client_id, *psw;
+  char *expected_psw;
+  int client_exists = GNUNET_NO;
+  struct MHD_Response *resp;
+  char* code_output;
+  json_t *root, *ticket_string, *nonce, *max_age;
+  json_error_t error;
+  char *json_response;
+  char *jwt_secret;
+
+  /*
+   * Check Authorization
+   */
+  GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
+                      strlen (OIDC_AUTHORIZATION_HEADER_KEY),
+                      &cache_key);
+  if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map,
+                                                            &cache_key) )
+  {
+    handle->emsg=GNUNET_strdup("invalid_client");
+    handle->edesc=GNUNET_strdup("missing authorization");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  authorization = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key);
+
+  //split header in "Basic" and [content]
+  credentials = strtok (authorization, delimiter);
+  if (0 != strcmp ("Basic",credentials))
+  {
+    handle->emsg=GNUNET_strdup("invalid_client");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  credentials = strtok(NULL, delimiter);
+  if (NULL == credentials)
+  {
+    handle->emsg=GNUNET_strdup("invalid_client");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  GNUNET_STRINGS_base64_decode (credentials, strlen (credentials), (void**)&user_psw);
+
+  if ( NULL == user_psw )
+  {
+    handle->emsg=GNUNET_strdup("invalid_client");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  client_id = strtok (user_psw, delimiter_user_psw);
+  if ( NULL == client_id )
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg=GNUNET_strdup("invalid_client");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  psw = strtok (NULL, delimiter_user_psw);
+  if (NULL == psw)
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg=GNUNET_strdup("invalid_client");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  //check client password
+  if ( GNUNET_OK
+       == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin",
+                                                 "psw", &expected_psw) )
+  {
+    if (0 != strcmp (expected_psw, psw))
+    {
+      GNUNET_free_non_null(user_psw);
+      GNUNET_free(expected_psw);
+      handle->emsg=GNUNET_strdup("invalid_client");
+      handle->response_code = MHD_HTTP_UNAUTHORIZED;
+      GNUNET_SCHEDULER_add_now (&do_error, handle);
+      return;
+    }
+    GNUNET_free(expected_psw);
+  }
+  else
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg = GNUNET_strdup("server_error");
+    handle->edesc = GNUNET_strdup ("gnunet configuration failed");
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  //check client_id
+  for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry->next; )
+  {
+    if ( 0 == strcmp(handle->ego_entry->keystring, client_id))
+    {
+      client_exists = GNUNET_YES;
+      break;
+    }
+    handle->ego_entry = handle->ego_entry->next;
+  }
+  if (GNUNET_NO == client_exists)
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg=GNUNET_strdup("invalid_client");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  /*
+   * Check parameter
+   */
+
+  //TODO Do not allow multiple equal parameter names
+  //REQUIRED grant_type
+  GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY, strlen (OIDC_GRANT_TYPE_KEY), &cache_key);
+  if ( GNUNET_NO
+       == GNUNET_CONTAINER_multihashmap_contains (
+                                                  handle->rest_handle->url_param_map, &cache_key) )
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("missing parameter grant_type");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  grant_type = GNUNET_CONTAINER_multihashmap_get (
+                                                  handle->rest_handle->url_param_map, &cache_key);
+
+  //REQUIRED code
+  GNUNET_CRYPTO_hash (OIDC_CODE_KEY, strlen (OIDC_CODE_KEY), &cache_key);
+  if ( GNUNET_NO
+       == GNUNET_CONTAINER_multihashmap_contains (
+                                                  handle->rest_handle->url_param_map, &cache_key) )
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("missing parameter code");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  code = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
+                                            &cache_key);
+
+  //REQUIRED redirect_uri
+  GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY),
+                      &cache_key);
+  if ( GNUNET_NO
+       == GNUNET_CONTAINER_multihashmap_contains (
+                                                  handle->rest_handle->url_param_map, &cache_key) )
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("missing parameter redirect_uri");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  //Check parameter grant_type == "authorization_code"
+  if (0 != strcmp(OIDC_GRANT_TYPE_VALUE, grant_type))
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg=GNUNET_strdup("unsupported_grant_type");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  GNUNET_CRYPTO_hash (code, strlen (code), &cache_key);
+  int i = 1;
+  if ( GNUNET_SYSERR
+       == GNUNET_CONTAINER_multihashmap_put (OIDC_ticket_once,
+                                             &cache_key,
+                                             &i,
+                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) )
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("Cannot use the same code more than once");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  //decode code
+  GNUNET_STRINGS_base64_decode(code,strlen(code), (void**)&code_output);
+  root = json_loads (code_output, 0, &error);
+  GNUNET_free(code_output);
+  ticket_string = json_object_get (root, "ticket");
+  nonce = json_object_get (root, "nonce");
+  max_age = json_object_get (root, "max_age");
+
+  if(ticket_string == NULL && !json_is_string(ticket_string))
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("invalid code");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  struct GNUNET_RECLAIM_Ticket *ticket = GNUNET_new(struct GNUNET_RECLAIM_Ticket);
+  if ( GNUNET_OK
+       != GNUNET_STRINGS_string_to_data (json_string_value(ticket_string),
+                                         strlen (json_string_value(ticket_string)),
+                                         ticket,
+                                         sizeof(struct GNUNET_RECLAIM_Ticket)))
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("invalid code");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    GNUNET_free(ticket);
+    return;
+  }
+  // this is the current client (relying party)
+  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
+  GNUNET_IDENTITY_ego_get_public_key(handle->ego_entry->ego,&pub_key);
+  if (0 != memcmp(&pub_key,&ticket->audience,sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("invalid code");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    GNUNET_free(ticket);
+    return;
+  }
+
+  //create jwt
+  unsigned long long int expiration_time;
+  if ( GNUNET_OK
+       != GNUNET_CONFIGURATION_get_value_number(cfg, "identity-rest-plugin",
+                                                "expiration_time", &expiration_time) )
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg = GNUNET_strdup("server_error");
+    handle->edesc = GNUNET_strdup ("gnunet configuration failed");
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    GNUNET_free(ticket);
+    return;
+  }
+
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *cl = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
+  //aud REQUIRED public key client_id must be there
+  GNUNET_RECLAIM_ATTRIBUTE_list_add(cl,
+                                     "aud",
+                                     GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
+                                     client_id,
+                                     strlen(client_id));
+  //exp REQUIRED time expired from config
+  struct GNUNET_TIME_Absolute exp_time = GNUNET_TIME_relative_to_absolute (
+                                                                           GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (),
+                                                                                                          expiration_time));
+  const char* exp_time_string = GNUNET_STRINGS_absolute_time_to_string(exp_time);
+  GNUNET_RECLAIM_ATTRIBUTE_list_add (cl,
+                                      "exp",
+                                      GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
+                                      exp_time_string,
+                                      strlen(exp_time_string));
+  //iat REQUIRED time now
+  struct GNUNET_TIME_Absolute time_now = GNUNET_TIME_absolute_get();
+  const char* time_now_string = GNUNET_STRINGS_absolute_time_to_string(time_now);
+  GNUNET_RECLAIM_ATTRIBUTE_list_add (cl,
+                                      "iat",
+                                      GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
+                                      time_now_string,
+                                      strlen(time_now_string));
+  //nonce only if nonce is provided
+  if ( NULL != nonce && json_is_string(nonce) )
+  {
+    GNUNET_RECLAIM_ATTRIBUTE_list_add (cl,
+                                        "nonce",
+                                        GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
+                                        json_string_value(nonce),
+                                        strlen(json_string_value(nonce)));
+  }
+  //auth_time only if max_age is provided
+  if ( NULL != max_age && json_is_string(max_age) )
+  {
+    GNUNET_RECLAIM_ATTRIBUTE_list_add (cl,
+                                        "auth_time",
+                                        GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
+                                        json_string_value(max_age),
+                                        strlen(json_string_value(max_age)));
+  }
+  //TODO OPTIONAL acr,amr,azp
+
+  struct EgoEntry *ego_entry;
+  for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next)
+  {
+    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
+    if (0 == memcmp (&pub_key, &ticket->audience, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
+    {
+      break;
+    }
+  }
+  if ( NULL == ego_entry )
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("invalid code...");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    GNUNET_free(ticket);
+    return;
+  }
+  if ( GNUNET_OK
+       != GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin",
+                                                 "jwt_secret", &jwt_secret) )
+  {
+    GNUNET_free_non_null(user_psw);
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("No signing secret configured!");
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    GNUNET_free(ticket);
+    return;
+  }
+  struct GNUNET_CRYPTO_AuthKey jwt_sign_key;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
+  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pk);
+  GNUNET_CRYPTO_hash (jwt_secret, strlen (jwt_secret), (struct GNUNET_HashCode*)jwt_sign_key.key);
+  char *id_token = jwt_create_from_list(&ticket->audience,
+                                        &pk,
+                                        cl,
+                                        &jwt_sign_key);
+
+  //Create random access_token
+  char* access_token_number;
+  char* access_token;
+  uint64_t random_number;
+  random_number = GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
+  GNUNET_asprintf(&access_token_number, "%" PRIu64, random_number);
+  GNUNET_STRINGS_base64_encode(access_token_number,strlen(access_token_number),&access_token);
+
+
+
+  //TODO OPTIONAL add refresh_token and scope
+  GNUNET_asprintf (&json_response,
+                   "{ \"access_token\" : \"%s\", "
+                   "\"token_type\" : \"Bearer\", "
+                   "\"expires_in\" : %d, "
+                   "\"id_token\" : \"%s\"}",
+                   access_token,
+                   expiration_time,
+                   id_token);
+  GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key);
+  char *id_ticket_combination;
+  GNUNET_asprintf(&id_ticket_combination,
+                  "%s;%s",
+                  client_id,
+                  json_string_value(ticket_string));
+  GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token,
+                                    &cache_key,
+                                    id_ticket_combination,
+                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+
+  resp = GNUNET_REST_create_response (json_response);
+  MHD_add_response_header (resp, "Cache-Control", "no-store");
+  MHD_add_response_header (resp, "Pragma", "no-cache");
+  MHD_add_response_header (resp, "Content-Type", "application/json");
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+
+  GNUNET_RECLAIM_ATTRIBUTE_list_destroy(cl);
+  GNUNET_free(access_token_number);
+  GNUNET_free(access_token);
+  GNUNET_free(user_psw);
+  GNUNET_free(json_response);
+  GNUNET_free(ticket);
+  GNUNET_free(id_token);
+  json_decref (root);
+  GNUNET_SCHEDULER_add_now(&cleanup_handle_delayed, handle);
+}
+
+/**
+ * Collects claims and stores them in handle
+ */
+static void
+consume_ticket (void *cls,
+                const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+                const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+{
+  struct RequestHandle *handle = cls;
+  char *tmp_value;
+  json_t *value;
+
+  if (NULL == identity)
+  {
+    GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle);
+    return;
+  }
+
+  tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
+                                                         attr->data,
+                                                         attr->data_size);
+
+  value = json_string (tmp_value);
+
+
+  json_object_set_new (handle->oidc->response,
+                       attr->name,
+                       value);
+  GNUNET_free (tmp_value);
+}
+
+/**
+ * Responds to userinfo GET and url-encoded POST request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
+                   const char* url, void *cls)
+{
+  //TODO expiration time
+  struct RequestHandle *handle = cls;
+  char delimiter[] = " ";
+  char delimiter_db[] = ";";
+  struct GNUNET_HashCode cache_key;
+  char *authorization, *authorization_type, *authorization_access_token;
+  char *client_ticket, *client, *ticket_str;
+  struct GNUNET_RECLAIM_Ticket *ticket;
+
+  GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
+                      strlen (OIDC_AUTHORIZATION_HEADER_KEY),
+                      &cache_key);
+  if ( GNUNET_NO
+       == GNUNET_CONTAINER_multihashmap_contains (
+                                                  handle->rest_handle->header_param_map, &cache_key) )
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("No Access Token");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    return;
+  }
+  authorization = GNUNET_CONTAINER_multihashmap_get (
+                                                     handle->rest_handle->header_param_map, &cache_key);
+
+  //split header in "Bearer" and access_token
+  authorization = GNUNET_strdup(authorization);
+  authorization_type = strtok (authorization, delimiter);
+  if ( 0 != strcmp ("Bearer", authorization_type) )
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("No Access Token");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    GNUNET_free(authorization);
+    return;
+  }
+  authorization_access_token = strtok (NULL, delimiter);
+  if ( NULL == authorization_access_token )
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("No Access Token");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    GNUNET_free(authorization);
+    return;
+  }
+
+  GNUNET_CRYPTO_hash (authorization_access_token,
+                      strlen (authorization_access_token),
+                      &cache_key);
+  if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (OIDC_interpret_access_token,
+                                                            &cache_key) )
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("The Access Token expired");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    GNUNET_free(authorization);
+    return;
+  }
+
+  client_ticket = GNUNET_CONTAINER_multihashmap_get(OIDC_interpret_access_token,
+                                                    &cache_key);
+  client_ticket = GNUNET_strdup(client_ticket);
+  client = strtok(client_ticket,delimiter_db);
+  if (NULL == client)
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("The Access Token expired");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    GNUNET_free(authorization);
+    GNUNET_free(client_ticket);
+    return;
+  }
+  handle->ego_entry = handle->ego_head;
+  for(; NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next)
+  {
+    if (0 == strcmp(handle->ego_entry->keystring,client))
+    {
+      break;
+    }
+  }
+  if (NULL == handle->ego_entry)
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("The Access Token expired");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    GNUNET_free(authorization);
+    GNUNET_free(client_ticket);
+    return;
+  }
+  ticket_str = strtok(NULL, delimiter_db);
+  if (NULL == ticket_str)
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("The Access Token expired");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    GNUNET_free(authorization);
+    GNUNET_free(client_ticket);
+    return;
+  }
+  ticket = GNUNET_new(struct GNUNET_RECLAIM_Ticket);
+  if ( GNUNET_OK
+       != GNUNET_STRINGS_string_to_data (ticket_str,
+                                         strlen (ticket_str),
+                                         ticket,
+                                         sizeof(struct GNUNET_RECLAIM_Ticket)))
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("The Access Token expired");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    GNUNET_free(ticket);
+    GNUNET_free(authorization);
+    GNUNET_free(client_ticket);
+    return;
+  }
+
+  handle->idp = GNUNET_RECLAIM_connect (cfg);
+  handle->oidc->response = json_object();
+  json_object_set_new( handle->oidc->response, "sub", json_string( handle->ego_entry->keystring));
+  handle->idp_op = GNUNET_RECLAIM_ticket_consume (
+                                                            handle->idp,
+                                                            GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego),
+                                                            ticket,
+                                                            consume_ticket,
+                                                            handle);
+  GNUNET_free(ticket);
+  GNUNET_free(authorization);
+  GNUNET_free(client_ticket);
+
+}
+
+
+/**
+ * Handle rest request
+ *
+ * @param handle the request handle
+ */
+static void
+init_cont (struct RequestHandle *handle)
+{
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] = {
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint}, //url-encoded
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
+    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC,
+      &options_cont},
+    GNUNET_REST_HANDLER_END
+  };
+
+  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
+                                               handlers,
+                                               &err,
+                                               handle))
+  {
+    handle->response_code = err.error_code;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+  }
+}
+
+/**
+ * If listing is enabled, prints information about the egos.
+ *
+ * This function is initially called for all egos and then again
+ * whenever a ego's identifier changes or if it is deleted.  At the
+ * end of the initial pass over all egos, the function is once called
+ * with 'NULL' for 'ego'. That does NOT mean that the callback won't
+ * be invoked in the future or that there was an error.
+ *
+ * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
+ * this function is only called ONCE, and 'NULL' being passed in
+ * 'ego' does indicate an error (i.e. name is taken or no default
+ * value is known).  If 'ego' is non-NULL and if '*ctx'
+ * is set in those callbacks, the value WILL be passed to a subsequent
+ * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
+ * that one was not NULL).
+ *
+ * When an identity is renamed, this function is called with the
+ * (known) ego but the NEW identifier.
+ *
+ * When an identity is deleted, this function is called with the
+ * (known) ego and "NULL" for the 'identifier'.  In this case,
+ * the 'ego' is henceforth invalid (and the 'ctx' should also be
+ * cleaned up).
+ *
+ * @param cls closure
+ * @param ego ego handle
+ * @param ctx context for application to store data for this ego
+ *                 (during the lifetime of this process, initially NULL)
+ * @param identifier identifier 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
+list_ego (void *cls,
+          struct GNUNET_IDENTITY_Ego *ego,
+          void **ctx,
+          const char *identifier)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
+
+  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
+  {
+    handle->state = ID_REST_STATE_POST_INIT;
+    init_cont (handle);
+    return;
+  }
+  if (ID_REST_STATE_INIT == handle->state) {
+    ego_entry = GNUNET_new (struct EgoEntry);
+    GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
+    ego_entry->keystring =
+      GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
+    ego_entry->ego = ego;
+    ego_entry->identifier = GNUNET_strdup (identifier);
+    GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
+    return;
+  }
+  /* Ego renamed or added */
+  if (identifier != NULL) {
+    for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) {
+      if (ego_entry->ego == ego) {
+        /* Rename */
+        GNUNET_free (ego_entry->identifier);
+        ego_entry->identifier = GNUNET_strdup (identifier);
+        break;
+      }
+    }
+    if (NULL == ego_entry) {
+      /* Add */
+      ego_entry = GNUNET_new (struct EgoEntry);
+      GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
+      ego_entry->keystring =
+        GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
+      ego_entry->ego = ego;
+      ego_entry->identifier = GNUNET_strdup (identifier);
+      GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
+    }
+  } else {
+    /* Delete */
+    for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) {
+      if (ego_entry->ego == ego)
+        break;
+    }
+    if (NULL != ego_entry)
+      GNUNET_CONTAINER_DLL_remove(handle->ego_head,handle->ego_tail, ego_entry);
+  }
+
+}
+
+static void
+rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
+                              GNUNET_REST_ResultProcessor proc,
+                              void *proc_cls)
+{
+  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  handle->oidc = GNUNET_new (struct OIDC_Variables);
+  if ( NULL == OIDC_identity_login_time )
+    OIDC_identity_login_time = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
+  if ( NULL == OIDC_identity_grants )
+    OIDC_identity_grants = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
+  if ( NULL == OIDC_ticket_once )
+    OIDC_ticket_once = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
+  if ( NULL == OIDC_interpret_access_token )
+    OIDC_interpret_access_token = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
+  handle->response_code = 0;
+  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+  handle->proc_cls = proc_cls;
+  handle->proc = proc;
+  handle->state = ID_REST_STATE_INIT;
+  handle->rest_handle = rest_handle;
+
+  handle->url = GNUNET_strdup (rest_handle->url);
+  if (handle->url[strlen (handle->url)-1] == '/')
+    handle->url[strlen (handle->url)-1] = '\0';
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connecting...\n");
+  handle->identity_handle = GNUNET_IDENTITY_connect (cfg,
+                                                     &list_ego,
+                                                     handle);
+  handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg);
+  handle->timeout_task =
+    GNUNET_SCHEDULER_add_delayed (handle->timeout,
+                                  &do_timeout,
+                                  handle);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connected\n");
+}
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls Config info
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_rest_openid_connect_init (void *cls)
+{
+  static struct Plugin plugin;
+  struct GNUNET_REST_Plugin *api;
+
+  cfg = cls;
+  if (NULL != plugin.cfg)
+    return NULL;                /* can only initialize once! */
+  memset (&plugin, 0, sizeof (struct Plugin));
+  plugin.cfg = cfg;
+  api = GNUNET_new (struct GNUNET_REST_Plugin);
+  api->cls = &plugin;
+  api->name = GNUNET_REST_API_NS_OIDC;
+  api->process_request = &rest_identity_process_request;
+  GNUNET_asprintf (&allow_methods,
+                   "%s, %s, %s, %s, %s",
+                   MHD_HTTP_METHOD_GET,
+                   MHD_HTTP_METHOD_POST,
+                   MHD_HTTP_METHOD_PUT,
+                   MHD_HTTP_METHOD_DELETE,
+                   MHD_HTTP_METHOD_OPTIONS);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              _("Identity Provider REST API initialized\n"));
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_rest_openid_connect_done (void *cls)
+{
+  struct GNUNET_REST_Plugin *api = cls;
+  struct Plugin *plugin = api->cls;
+  plugin->cfg = NULL;
+
+  struct GNUNET_CONTAINER_MultiHashMapIterator *hashmap_it;
+  void *value = NULL;
+  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (
+                                                              OIDC_identity_login_time);
+  while (GNUNET_YES ==
+         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
+  {
+    if (NULL != value)
+      GNUNET_free(value);
+  }
+  GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_login_time);
+  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_identity_grants);
+  while (GNUNET_YES ==
+         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
+  {
+    if (NULL != value)
+      GNUNET_free(value);
+  }
+  GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_grants);
+  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_ticket_once);
+  while (GNUNET_YES ==
+         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
+  {
+    if (NULL != value)
+      GNUNET_free(value);
+  }
+  GNUNET_CONTAINER_multihashmap_destroy(OIDC_ticket_once);
+  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_interpret_access_token);
+  while (GNUNET_YES ==
+         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
+  {
+    if (NULL != value)
+      GNUNET_free(value);
+  }
+  GNUNET_CONTAINER_multihashmap_destroy(OIDC_interpret_access_token);
+  GNUNET_CONTAINER_multihashmap_iterator_destroy(hashmap_it);
+  GNUNET_free_non_null (allow_methods);
+  GNUNET_free (api);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Identity Provider REST plugin is finished\n");
+  return NULL;
+}
+
+/* end of plugin_rest_identity_provider.c */
diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c
new file mode 100644 (file)
index 0000000..b54aed5
--- /dev/null
@@ -0,0 +1,1253 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+  
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @author Philippe Buschmann
+ * @file reclaim/plugin_rest_reclaim.c
+ * @brief GNUnet reclaim REST plugin
+ *
+ */
+
+#include "platform.h"
+#include "gnunet_rest_plugin.h"
+#include "gnunet_identity_service.h"
+#include "gnunet_gns_service.h"
+#include "gnunet_gnsrecord_lib.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_rest_lib.h"
+#include "gnunet_jsonapi_lib.h"
+#include "gnunet_jsonapi_util.h"
+#include "microhttpd.h"
+#include <jansson.h>
+#include <inttypes.h>
+#include "gnunet_signatures.h"
+#include "gnunet_reclaim_attribute_lib.h"
+#include "gnunet_reclaim_service.h"
+
+/**
+ * REST root namespace
+ */
+#define GNUNET_REST_API_NS_RECLAIM "/idp"
+
+/**
+ * Attribute namespace
+ */
+#define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/idp/attributes"
+
+/**
+ * Ticket namespace
+ */
+#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/idp/tickets"
+
+/**
+ * Revoke namespace
+ */
+#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/idp/revoke"
+
+/**
+ * Revoke namespace
+ */
+#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume"
+
+/**
+ * Attribute key
+ */
+#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE "attribute"
+
+/**
+ * Ticket key
+ */
+#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket"
+
+
+/**
+ * Value key
+ */
+#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE_VALUE "value"
+
+/**
+ * State while collecting all egos
+ */
+#define ID_REST_STATE_INIT 0
+
+/**
+ * Done collecting egos
+ */
+#define ID_REST_STATE_POST_INIT 1
+
+/**
+ * The configuration handle
+ */
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * HTTP methods allows for this plugin
+ */
+static char* allow_methods;
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct Plugin
+{
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+};
+
+/**
+ * The ego list
+ */
+struct EgoEntry
+{
+  /**
+   * DLL
+   */
+  struct EgoEntry *next;
+
+  /**
+   * DLL
+   */
+  struct EgoEntry *prev;
+
+  /**
+   * Ego Identifier
+   */
+  char *identifier;
+
+  /**
+   * Public key string
+   */
+  char *keystring;
+
+  /**
+   * The Ego
+   */
+  struct GNUNET_IDENTITY_Ego *ego;
+};
+
+
+struct RequestHandle
+{
+  /**
+   * Ego list
+   */
+  struct EgoEntry *ego_head;
+
+  /**
+   * Ego list
+   */
+  struct EgoEntry *ego_tail;
+
+  /**
+   * Selected ego
+   */
+  struct EgoEntry *ego_entry;
+
+  /**
+   * Pointer to ego private key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
+
+  /**
+   * The processing state
+   */
+  int state;
+
+  /**
+   * Handle to Identity service.
+   */
+  struct GNUNET_IDENTITY_Handle *identity_handle;
+
+  /**
+   * Rest connection
+   */
+  struct GNUNET_REST_RequestHandle *rest_handle;
+
+  /**
+   * Handle to NAMESTORE
+   */
+  struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+  /**
+   * Iterator for NAMESTORE
+   */
+  struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it;
+
+  /**
+   * Attribute claim list
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list;
+
+  /**
+   * IDENTITY Operation
+   */
+  struct GNUNET_IDENTITY_Operation *op;
+
+  /**
+   * Identity Provider
+   */
+  struct GNUNET_RECLAIM_Handle *idp;
+
+  /**
+   * Idp Operation
+   */
+  struct GNUNET_RECLAIM_Operation *idp_op;
+
+  /**
+   * Attribute iterator
+   */
+  struct GNUNET_RECLAIM_AttributeIterator *attr_it;
+
+  /**
+   * Ticket iterator
+   */
+  struct GNUNET_RECLAIM_TicketIterator *ticket_it;
+
+  /**
+   * A ticket
+   */
+  struct GNUNET_RECLAIM_Ticket ticket;
+
+  /**
+   * Desired timeout for the lookup (default is no timeout).
+   */
+  struct GNUNET_TIME_Relative timeout;
+
+  /**
+   * ID of a task associated with the resolution process.
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * The plugin result processor
+   */
+  GNUNET_REST_ResultProcessor proc;
+
+  /**
+   * The closure of the result processor
+   */
+  void *proc_cls;
+
+  /**
+   * The url
+   */
+  char *url;
+
+  /**
+   * Error response message
+   */
+  char *emsg;
+
+  /**
+   * Reponse code
+   */
+  int response_code;
+
+  /**
+   * Response object
+   */
+  struct GNUNET_JSONAPI_Document *resp_object;
+
+};
+
+/**
+ * Cleanup lookup handle
+ * @param handle Handle to clean up
+ */
+static void
+cleanup_handle (struct RequestHandle *handle)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_entry;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_tmp;
+  struct EgoEntry *ego_entry;
+  struct EgoEntry *ego_tmp;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up\n");
+  if (NULL != handle->resp_object)
+    GNUNET_JSONAPI_document_delete (handle->resp_object);
+  if (NULL != handle->timeout_task)
+    GNUNET_SCHEDULER_cancel (handle->timeout_task);
+  if (NULL != handle->identity_handle)
+    GNUNET_IDENTITY_disconnect (handle->identity_handle);
+  if (NULL != handle->attr_it)
+    GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
+  if (NULL != handle->ticket_it)
+    GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
+  if (NULL != handle->idp)
+    GNUNET_RECLAIM_disconnect (handle->idp);
+  if (NULL != handle->url)
+    GNUNET_free (handle->url);
+  if (NULL != handle->emsg)
+    GNUNET_free (handle->emsg);
+  if (NULL != handle->namestore_handle)
+    GNUNET_NAMESTORE_disconnect (handle->namestore_handle);
+  if ( NULL != handle->attr_list )
+  {
+    for (claim_entry = handle->attr_list->list_head;
+    NULL != claim_entry;)
+    {
+      claim_tmp = claim_entry;
+      claim_entry = claim_entry->next;
+      GNUNET_free(claim_tmp->claim);
+      GNUNET_free(claim_tmp);
+    }
+    GNUNET_free (handle->attr_list);
+  }
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;)
+  {
+    ego_tmp = ego_entry;
+    ego_entry = ego_entry->next;
+    GNUNET_free (ego_tmp->identifier);
+    GNUNET_free (ego_tmp->keystring);
+    GNUNET_free (ego_tmp);
+  }
+  if (NULL != handle->attr_it)
+  {
+    GNUNET_free(handle->attr_it);
+  }
+  GNUNET_free (handle);
+}
+
+static void
+cleanup_handle_delayed (void *cls)
+{
+  cleanup_handle (cls);
+}
+
+
+/**
+ * Task run on error, sends error message.  Cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  char *json_error;
+
+  GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\" }",
+                  handle->emsg);
+  if ( 0 == handle->response_code )
+  {
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+  }
+  resp = GNUNET_REST_create_response (json_error);
+  MHD_add_response_header (resp, "Content-Type", "application/json");
+  handle->proc (handle->proc_cls, resp, handle->response_code);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  GNUNET_free (json_error);
+}
+
+
+/**
+ * Task run on timeout, sends error message.  Cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_timeout (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  handle->timeout_task = NULL;
+  do_error (handle);
+}
+
+
+static void
+collect_error_cb (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  do_error (handle);
+}
+
+static void
+finished_cont (void *cls,
+               int32_t success,
+               const char *emsg)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+
+  resp = GNUNET_REST_create_response (emsg);
+  if (GNUNET_OK != success)
+  {
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+}
+
+
+/**
+ * Return attributes for identity
+ *
+ * @param cls the request handle
+ */
+static void
+return_response (void *cls)
+{
+  char* result_str;
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+
+  GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
+  resp = GNUNET_REST_create_response (result_str);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_free (result_str);
+  cleanup_handle (handle);
+}
+
+static void
+collect_finished_cb (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  //Done
+  handle->attr_it = NULL;
+  handle->ticket_it = NULL;
+  GNUNET_SCHEDULER_add_now (&return_response, handle);
+}
+
+
+/**
+ * Collect all attributes for an ego
+ *
+ */
+static void
+ticket_collect (void *cls,
+                const struct GNUNET_RECLAIM_Ticket *ticket)
+{
+  struct GNUNET_JSONAPI_Resource *json_resource;
+  struct RequestHandle *handle = cls;
+  json_t *value;
+  char* tmp;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
+  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
+                                             sizeof (uint64_t));
+  json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TICKET,
+                                                       tmp);
+  GNUNET_free (tmp);
+  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
+
+  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->identity,
+                                             sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  value = json_string (tmp);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "issuer",
+                                    value);
+  GNUNET_free (tmp);
+  json_decref (value);
+  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
+                                             sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  value = json_string (tmp);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "audience",
+                                    value);
+  GNUNET_free (tmp);
+  json_decref (value);
+  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
+                                             sizeof (uint64_t));
+  value = json_string (tmp);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "rnd",
+                                    value);
+  GNUNET_free (tmp);
+  json_decref (value);
+  GNUNET_RECLAIM_ticket_iteration_next (handle->ticket_it);
+}
+
+
+
+/**
+ * List tickets for identity request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                   const char* url,
+                   void *cls)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  char *identity;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting tickets for %s.\n",
+              handle->url);
+  if ( strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >=
+       strlen (handle->url))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
+
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+    if (0 == strcmp (identity, ego_entry->identifier))
+      break;
+  handle->resp_object = GNUNET_JSONAPI_document_new ();
+
+  if (NULL == ego_entry)
+  {
+    //Done
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
+                identity);
+    GNUNET_SCHEDULER_add_now (&return_response, handle);
+    return;
+  }
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+  handle->idp = GNUNET_RECLAIM_connect (cfg);
+  handle->ticket_it = GNUNET_RECLAIM_ticket_iteration_start (handle->idp,
+                                                                       priv_key,
+                                                                       &collect_error_cb,
+                                                                       handle,
+                                                                       &ticket_collect,
+                                                                       handle,
+                                                                       &collect_finished_cb,
+                                                                       handle);
+}
+
+
+static void
+add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                    const char* url,
+                    void *cls)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+  const char* identity;
+  const char* name_str;
+  const char* value_str;
+  const char* exp_str;
+
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct MHD_Response *resp;
+  struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attribute;
+  struct GNUNET_JSONAPI_Document *json_obj;
+  struct GNUNET_JSONAPI_Resource *json_res;
+  struct GNUNET_TIME_Relative exp;
+  char term_data[handle->rest_handle->data_size+1];
+  json_t *value_json;
+  json_t *data_json;
+  json_t *exp_json;
+  json_error_t err;
+  struct GNUNET_JSON_Specification docspec[] = {
+    GNUNET_JSON_spec_jsonapi_document (&json_obj),
+    GNUNET_JSON_spec_end()
+  };
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding an attribute for %s.\n",
+              handle->url);
+  if ( strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >=
+       strlen (handle->url))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
+
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+    if (0 == strcmp (identity, ego_entry->identifier))
+      break;
+
+  if (NULL == ego_entry)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Identity unknown (%s)\n", identity);
+    GNUNET_JSONAPI_document_delete (json_obj);
+    return;
+  }
+  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+
+  if (0 >= handle->rest_handle->data_size)
+  {
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  term_data[handle->rest_handle->data_size] = '\0';
+  GNUNET_memcpy (term_data,
+                 handle->rest_handle->data,
+                 handle->rest_handle->data_size);
+  data_json = json_loads (term_data,
+                          JSON_DECODE_ANY,
+                          &err);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_JSON_parse (data_json, docspec,
+                                    NULL, NULL));
+  json_decref (data_json);
+  if (NULL == json_obj)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to parse JSONAPI Object from %s\n",
+                term_data);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot create more than 1 resource! (Got %d)\n",
+                GNUNET_JSONAPI_document_resource_count (json_obj));
+    GNUNET_JSONAPI_document_delete (json_obj);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+                                                       GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unsupported JSON data type\n");
+    GNUNET_JSONAPI_document_delete (json_obj);
+    resp = GNUNET_REST_create_response (NULL);
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+    cleanup_handle (handle);
+    return;
+  }
+  name_str = GNUNET_JSONAPI_resource_get_id (json_res);
+  exp_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                "exp");
+  exp_str = json_string_value (exp_json);
+  if (NULL == exp_str) {
+    exp = GNUNET_TIME_UNIT_HOURS;
+  } else {
+    if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (exp_str,
+                                           &exp)) {
+      exp = GNUNET_TIME_UNIT_HOURS;
+    }
+  }
+
+  value_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                  "value");
+  value_str = json_string_value (value_json);
+  attribute = GNUNET_RECLAIM_ATTRIBUTE_claim_new (name_str,
+                                                      GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
+                                                      value_str,
+                                                      strlen (value_str) + 1);
+  handle->idp = GNUNET_RECLAIM_connect (cfg);
+  handle->idp_op = GNUNET_RECLAIM_attribute_store (handle->idp,
+                                                             identity_priv,
+                                                             attribute,
+                                                             &exp,
+                                                             &finished_cont,
+                                                             handle);
+  GNUNET_free (attribute);
+  GNUNET_JSONAPI_document_delete (json_obj);
+}
+
+
+
+/**
+ * Collect all attributes for an ego
+ *
+ */
+static void
+attr_collect (void *cls,
+              const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+              const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+{
+  struct GNUNET_JSONAPI_Resource *json_resource;
+  struct RequestHandle *handle = cls;
+  json_t *value;
+  char* tmp_value;
+  
+  if ((NULL == attr->name) || (NULL == attr->data))
+  {
+    GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
+              attr->name);
+  json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE,
+                                               attr->name);
+  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
+
+  tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
+                                           attr->data,
+                                           attr->data_size);
+
+  value = json_string (tmp_value);
+
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "value",
+                                    value);
+  json_decref (value);
+  GNUNET_free(tmp_value);
+  GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+}
+
+
+
+/**
+ * List attributes for identity request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                     const char* url,
+                     void *cls)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  char *identity;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting attributes for %s.\n",
+              handle->url);
+  if ( strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >=
+       strlen (handle->url))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
+
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+    if (0 == strcmp (identity, ego_entry->identifier))
+      break;
+  handle->resp_object = GNUNET_JSONAPI_document_new ();
+
+
+  if (NULL == ego_entry)
+  {
+    //Done
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
+                identity);
+    GNUNET_SCHEDULER_add_now (&return_response, handle);
+    return;
+  }
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+  handle->idp = GNUNET_RECLAIM_connect (cfg);
+  handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp,
+                                                                   priv_key,
+                                                                   &collect_error_cb,
+                                                                   handle,
+                                                                   &attr_collect,
+                                                                   handle,
+                                                                   &collect_finished_cb,
+                                                                   handle);
+}
+
+
+static void
+revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                    const char* url,
+                    void *cls)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+  const char* identity_str;
+  const char* audience_str;
+  const char* rnd_str;
+
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct MHD_Response *resp;
+  struct GNUNET_RECLAIM_Ticket ticket;
+  struct GNUNET_JSONAPI_Document *json_obj;
+  struct GNUNET_JSONAPI_Resource *json_res;
+  struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
+  char term_data[handle->rest_handle->data_size+1];
+  json_t *rnd_json;
+  json_t *identity_json;
+  json_t *audience_json;
+  json_t *data_json;
+  json_error_t err;
+  struct GNUNET_JSON_Specification docspec[] = {
+    GNUNET_JSON_spec_jsonapi_document (&json_obj),
+    GNUNET_JSON_spec_end()
+  };
+
+  if (0 >= handle->rest_handle->data_size)
+  {
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  term_data[handle->rest_handle->data_size] = '\0';
+  GNUNET_memcpy (term_data,
+                 handle->rest_handle->data,
+                 handle->rest_handle->data_size);
+  data_json = json_loads (term_data,
+                          JSON_DECODE_ANY,
+                          &err);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_JSON_parse (data_json, docspec,
+                                    NULL, NULL));
+  json_decref (data_json);
+  if (NULL == json_obj)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to parse JSONAPI Object from %s\n",
+                term_data);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot create more than 1 resource! (Got %d)\n",
+                GNUNET_JSONAPI_document_resource_count (json_obj));
+    GNUNET_JSONAPI_document_delete (json_obj);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+                                                       GNUNET_REST_JSONAPI_IDENTITY_TICKET))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unsupported JSON data type\n");
+    GNUNET_JSONAPI_document_delete (json_obj);
+    resp = GNUNET_REST_create_response (NULL);
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+    cleanup_handle (handle);
+    return;
+  }
+  rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                "rnd");
+  identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                     "issuer");
+  audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                     "audience");
+  rnd_str = json_string_value (rnd_json);
+  identity_str = json_string_value (identity_json);
+  audience_str = json_string_value (audience_json);
+
+  GNUNET_STRINGS_string_to_data (rnd_str,
+                                 strlen (rnd_str),
+                                 &ticket.rnd,
+                                 sizeof (uint64_t));
+  GNUNET_STRINGS_string_to_data (identity_str,
+                                 strlen (identity_str),
+                                 &ticket.identity,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  GNUNET_STRINGS_string_to_data (audience_str,
+                                 strlen (audience_str),
+                                 &ticket.audience,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+  {
+    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
+                                        &tmp_pk);
+    if (0 == memcmp (&ticket.identity,
+                     &tmp_pk,
+                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+      break;
+  }
+  if (NULL == ego_entry)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Identity unknown (%s)\n", identity_str);
+    GNUNET_JSONAPI_document_delete (json_obj);
+    return;
+  }
+  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+
+  handle->idp = GNUNET_RECLAIM_connect (cfg);
+  handle->idp_op = GNUNET_RECLAIM_ticket_revoke (handle->idp,
+                                                           identity_priv,
+                                                           &ticket,
+                                                           &finished_cont,
+                                                           handle);
+  GNUNET_JSONAPI_document_delete (json_obj);
+}
+
+static void
+consume_cont (void *cls,
+              const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+              const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_JSONAPI_Resource *json_resource;
+  json_t *value;
+
+  if (NULL == identity)
+  {
+    GNUNET_SCHEDULER_add_now (&return_response, handle);
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
+              attr->name);
+  json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE,
+                                               attr->name);
+  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
+
+  value = json_string (attr->data);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "value",
+                                    value);
+  json_decref (value);
+}
+
+static void
+consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                     const char* url,
+                     void *cls)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+  const char* identity_str;
+  const char* audience_str;
+  const char* rnd_str;
+
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct MHD_Response *resp;
+  struct GNUNET_RECLAIM_Ticket ticket;
+  struct GNUNET_JSONAPI_Document *json_obj;
+  struct GNUNET_JSONAPI_Resource *json_res;
+  struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
+  char term_data[handle->rest_handle->data_size+1];
+  json_t *rnd_json;
+  json_t *identity_json;
+  json_t *audience_json;
+  json_t *data_json;
+  json_error_t err;
+  struct GNUNET_JSON_Specification docspec[] = {
+    GNUNET_JSON_spec_jsonapi_document (&json_obj),
+    GNUNET_JSON_spec_end()
+  };
+
+  if (0 >= handle->rest_handle->data_size)
+  {
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  term_data[handle->rest_handle->data_size] = '\0';
+  GNUNET_memcpy (term_data,
+                 handle->rest_handle->data,
+                 handle->rest_handle->data_size);
+  data_json = json_loads (term_data,
+                          JSON_DECODE_ANY,
+                          &err);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_JSON_parse (data_json, docspec,
+                                    NULL, NULL));
+  json_decref (data_json);
+  if (NULL == json_obj)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to parse JSONAPI Object from %s\n",
+                term_data);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot create more than 1 resource! (Got %d)\n",
+                GNUNET_JSONAPI_document_resource_count (json_obj));
+    GNUNET_JSONAPI_document_delete (json_obj);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+                                                       GNUNET_REST_JSONAPI_IDENTITY_TICKET))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unsupported JSON data type\n");
+    GNUNET_JSONAPI_document_delete (json_obj);
+    resp = GNUNET_REST_create_response (NULL);
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+    cleanup_handle (handle);
+    return;
+  }
+  rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                "rnd");
+  identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                     "identity");
+  audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                     "audience");
+  rnd_str = json_string_value (rnd_json);
+  identity_str = json_string_value (identity_json);
+  audience_str = json_string_value (audience_json);
+
+  GNUNET_STRINGS_string_to_data (rnd_str,
+                                 strlen (rnd_str),
+                                 &ticket.rnd,
+                                 sizeof (uint64_t));
+  GNUNET_STRINGS_string_to_data (identity_str,
+                                 strlen (identity_str),
+                                 &ticket.identity,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  GNUNET_STRINGS_string_to_data (audience_str,
+                                 strlen (audience_str),
+                                 &ticket.audience,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+  {
+    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
+                                        &tmp_pk);
+    if (0 == memcmp (&ticket.audience,
+                     &tmp_pk,
+                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+      break;
+  }
+  if (NULL == ego_entry)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Identity unknown (%s)\n", identity_str);
+    GNUNET_JSONAPI_document_delete (json_obj);
+    return;
+  }
+  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+  handle->resp_object = GNUNET_JSONAPI_document_new ();
+  handle->idp = GNUNET_RECLAIM_connect (cfg);
+  handle->idp_op = GNUNET_RECLAIM_ticket_consume (handle->idp,
+                                                            identity_priv,
+                                                            &ticket,
+                                                            &consume_cont,
+                                                            handle);
+  GNUNET_JSONAPI_document_delete (json_obj);
+}
+
+
+
+/**
+ * Respond to OPTIONS request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+options_cont (struct GNUNET_REST_RequestHandle *con_handle,
+              const char* url,
+              void *cls)
+{
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  //For now, independent of path return all options
+  resp = GNUNET_REST_create_response (NULL);
+  MHD_add_response_header (resp,
+                           "Access-Control-Allow-Methods",
+                           allow_methods);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  cleanup_handle (handle);
+  return;
+}
+
+/**
+ * Handle rest request
+ *
+ * @param handle the request handle
+ */
+static void
+init_cont (struct RequestHandle *handle)
+{
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] = {
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &list_attribute_cont},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &add_attribute_cont},
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont},
+    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_RECLAIM,
+      &options_cont},
+    GNUNET_REST_HANDLER_END
+  };
+
+  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
+                                               handlers,
+                                               &err,
+                                               handle))
+  {
+    handle->response_code = err.error_code;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+  }
+}
+
+/**
+ * If listing is enabled, prints information about the egos.
+ *
+ * This function is initially called for all egos and then again
+ * whenever a ego's identifier changes or if it is deleted.  At the
+ * end of the initial pass over all egos, the function is once called
+ * with 'NULL' for 'ego'. That does NOT mean that the callback won't
+ * be invoked in the future or that there was an error.
+ *
+ * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
+ * this function is only called ONCE, and 'NULL' being passed in
+ * 'ego' does indicate an error (i.e. name is taken or no default
+ * value is known).  If 'ego' is non-NULL and if '*ctx'
+ * is set in those callbacks, the value WILL be passed to a subsequent
+ * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
+ * that one was not NULL).
+ *
+ * When an identity is renamed, this function is called with the
+ * (known) ego but the NEW identifier.
+ *
+ * When an identity is deleted, this function is called with the
+ * (known) ego and "NULL" for the 'identifier'.  In this case,
+ * the 'ego' is henceforth invalid (and the 'ctx' should also be
+ * cleaned up).
+ *
+ * @param cls closure
+ * @param ego ego handle
+ * @param ctx context for application to store data for this ego
+ *                 (during the lifetime of this process, initially NULL)
+ * @param identifier identifier 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
+list_ego (void *cls,
+          struct GNUNET_IDENTITY_Ego *ego,
+          void **ctx,
+          const char *identifier)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
+
+  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
+  {
+    handle->state = ID_REST_STATE_POST_INIT;
+    init_cont (handle);
+    return;
+  }
+  if (ID_REST_STATE_INIT == handle->state) {
+    ego_entry = GNUNET_new (struct EgoEntry);
+    GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
+    ego_entry->keystring =
+      GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
+    ego_entry->ego = ego;
+    ego_entry->identifier = GNUNET_strdup (identifier);
+    GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
+  }
+
+}
+
+static void
+rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
+                              GNUNET_REST_ResultProcessor proc,
+                              void *proc_cls)
+{
+  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  handle->response_code = 0;
+  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+  handle->proc_cls = proc_cls;
+  handle->proc = proc;
+  handle->state = ID_REST_STATE_INIT;
+  handle->rest_handle = rest_handle;
+
+  handle->url = GNUNET_strdup (rest_handle->url);
+  if (handle->url[strlen (handle->url)-1] == '/')
+    handle->url[strlen (handle->url)-1] = '\0';
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connecting...\n");
+  handle->identity_handle = GNUNET_IDENTITY_connect (cfg,
+                                                     &list_ego,
+                                                     handle);
+  handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg);
+  handle->timeout_task =
+    GNUNET_SCHEDULER_add_delayed (handle->timeout,
+                                  &do_timeout,
+                                  handle);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connected\n");
+}
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls Config info
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_rest_reclaim_init (void *cls)
+{
+  static struct Plugin plugin;
+  struct GNUNET_REST_Plugin *api;
+
+  cfg = cls;
+  if (NULL != plugin.cfg)
+    return NULL;                /* can only initialize once! */
+  memset (&plugin, 0, sizeof (struct Plugin));
+  plugin.cfg = cfg;
+  api = GNUNET_new (struct GNUNET_REST_Plugin);
+  api->cls = &plugin;
+  api->name = GNUNET_REST_API_NS_RECLAIM;
+  api->process_request = &rest_identity_process_request;
+  GNUNET_asprintf (&allow_methods,
+                   "%s, %s, %s, %s, %s",
+                   MHD_HTTP_METHOD_GET,
+                   MHD_HTTP_METHOD_POST,
+                   MHD_HTTP_METHOD_PUT,
+                   MHD_HTTP_METHOD_DELETE,
+                   MHD_HTTP_METHOD_OPTIONS);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              _("Identity Provider REST API initialized\n"));
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_rest_reclaim_done (void *cls)
+{
+  struct GNUNET_REST_Plugin *api = cls;
+  struct Plugin *plugin = api->cls;
+  plugin->cfg = NULL;
+
+  GNUNET_free_non_null (allow_methods);
+  GNUNET_free (api);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Identity Provider REST plugin is finished\n");
+  return NULL;
+}
+
+/* end of plugin_rest_reclaim.c */
diff --git a/src/reclaim/reclaim.conf b/src/reclaim/reclaim.conf
new file mode 100644 (file)
index 0000000..e93899e
--- /dev/null
@@ -0,0 +1,23 @@
+[reclaim]
+START_ON_DEMAND = NO
+RUN_PER_USER = YES
+#PORT = 2108
+HOSTNAME = localhost
+BINARY = gnunet-service-reclaim
+ACCEPT_FROM = 127.0.0.1;
+ACCEPT_FROM6 = ::1;
+UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-reclaim.sock
+UNIX_MATCH_UID = NO
+UNIX_MATCH_GID = YES
+TOKEN_EXPIRATION_INTERVAL = 30 m
+DATABASE = sqlite
+
+[reclaim-rest-plugin]
+#ADDRESS = https://identity.gnu:8000#/login
+ADDRESS = https://reclaim.ui/#/login
+PSW = secret
+JWT_SECRET = secret
+EXPIRATION_TIME = 3600
+
+[reclaim-sqlite]
+FILENAME = $GNUNET_DATA_HOME/reclaim/sqlite.db
diff --git a/src/reclaim/reclaim.h b/src/reclaim/reclaim.h
new file mode 100644 (file)
index 0000000..d2c8468
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2016 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @author Martin Schanzenbach
+ * @file reclaim/reclaim.h
+ *
+ * @brief Common type definitions for the identity provider
+ *        service and API.
+ */
+#ifndef RECLAIM_H
+#define RECLAIM_H
+
+#include "gnunet_common.h"
+
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Use to store an identity attribute
+ */
+struct AttributeStoreMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * The length of the attribute
+   */
+  uint32_t attr_len GNUNET_PACKED;
+
+  /**
+   * The expiration interval of the attribute
+   */
+  uint64_t exp GNUNET_PACKED;
+
+  /**
+   * Identity
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /* followed by the serialized attribute */
+
+};
+
+/**
+ * Attribute store response message
+ */
+struct AttributeStoreResultMessage
+{
+  /**
+   * Message header
+   */
+  struct GNUNET_MessageHeader header;
+  
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * #GNUNET_SYSERR on failure, #GNUNET_OK on success
+   */
+  int32_t op_result GNUNET_PACKED;
+
+};
+
+/**
+ * Attribute is returned from the idp.
+ */
+struct AttributeResultMessage
+{
+  /**
+   * Message header
+   */
+  struct GNUNET_MessageHeader header;
+
+   /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Length of serialized attribute data
+   */
+  uint16_t attr_len GNUNET_PACKED;
+
+  /**
+   * always zero (for alignment)
+   */
+  uint16_t reserved GNUNET_PACKED;
+
+  /**
+   * The public key of the identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
+
+  /* followed by:
+   * serialized attribute data
+   */
+};
+
+
+/**
+ * Start a attribute iteration for the given identity
+ */
+struct AttributeIterationStartMessage
+{
+  /**
+   * Message
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+};
+
+
+/**
+ * Ask for next result of attribute iteration for the given operation
+ */
+struct AttributeIterationNextMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+};
+
+
+/**
+ * Stop attribute iteration for the given operation
+ */
+struct AttributeIterationStopMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+};
+
+/**
+ * Start a ticket iteration for the given identity
+ */
+struct TicketIterationStartMessage
+{
+  /**
+   * Message
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
+
+  /**
+   * Identity is audience or issuer
+   */
+  uint32_t is_audience GNUNET_PACKED;
+};
+
+
+/**
+ * Ask for next result of ticket iteration for the given operation
+ */
+struct TicketIterationNextMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+};
+
+
+/**
+ * Stop ticket iteration for the given operation
+ */
+struct TicketIterationStopMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+};
+
+
+
+/**
+ * Ticket issue message
+ */
+struct IssueTicketMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * Requesting party.
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey rp;
+
+  /**
+   * length of serialized attribute list
+   */
+  uint32_t attr_len GNUNET_PACKED;
+
+  //Followed by a serialized attribute list
+};
+
+/**
+ * Ticket revoke message
+ */
+struct RevokeTicketMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * length of serialized attribute list
+   */
+  uint32_t attrs_len GNUNET_PACKED;
+
+  //Followed by a ticket and serialized attribute list
+};
+
+/**
+ * Ticket revoke message
+ */
+struct RevokeTicketResultMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Revocation result
+   */
+  uint32_t success GNUNET_PACKED;
+};
+
+
+/**
+ * Ticket result message
+ */
+struct TicketResultMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+};
+
+/**
+ * Ticket consume message
+ */
+struct ConsumeTicketMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  //Followed by a serialized ticket
+};
+
+/**
+ * Attribute list is returned from the idp.
+ */
+struct ConsumeTicketResultMessage
+{
+  /**
+   * Message header
+   */
+  struct GNUNET_MessageHeader header;
+
+   /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Length of serialized attribute data
+   */
+  uint16_t attrs_len GNUNET_PACKED;
+
+  /**
+   * always zero (for alignment)
+   */
+  uint16_t reserved GNUNET_PACKED;
+
+  /**
+   * The public key of the identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
+
+  /* followed by:
+   * serialized attributes data
+   */
+};
+
+
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
diff --git a/src/reclaim/reclaim_api.c b/src/reclaim/reclaim_api.c
new file mode 100644 (file)
index 0000000..3f1584c
--- /dev/null
@@ -0,0 +1,1383 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2016 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file reclaim/reclaim_api.c
+ * @brief api to interact with the reclaim service
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_protocols.h"
+#include "gnunet_mq_lib.h"
+#include "gnunet_reclaim_service.h"
+#include "gnunet_reclaim_attribute_lib.h"
+#include "reclaim.h"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "reclaim-api",__VA_ARGS__)
+
+
+/**
+ * Handle for an operation with the service.
+ */
+struct GNUNET_RECLAIM_Operation
+{
+
+  /**
+   * Main handle.
+   */
+  struct GNUNET_RECLAIM_Handle *h;
+
+  /**
+   * We keep operations in a DLL.
+   */
+  struct GNUNET_RECLAIM_Operation *next;
+
+  /**
+   * We keep operations in a DLL.
+   */
+  struct GNUNET_RECLAIM_Operation *prev;
+
+  /**
+   * Message to send to the service.
+   * Allocated at the end of this struct.
+   */
+  const struct GNUNET_MessageHeader *msg;
+
+  /**
+   * Continuation to invoke after attribute store call
+   */
+  GNUNET_RECLAIM_ContinuationWithStatus as_cb;
+
+  /**
+   * Attribute result callback
+   */
+  GNUNET_RECLAIM_AttributeResult ar_cb;
+
+  /**
+   * Revocation result callback
+   */
+  GNUNET_RECLAIM_ContinuationWithStatus rvk_cb;
+
+  /**
+   * Ticket result callback
+   */
+  GNUNET_RECLAIM_TicketCallback tr_cb;
+
+  /**
+   * Envelope with the message for this queue entry.
+   */
+  struct GNUNET_MQ_Envelope *env;
+
+  /**
+   * request id
+   */
+  uint32_t r_id;
+
+  /**
+   * Closure for @e cont or @e cb.
+   */
+  void *cls;
+
+};
+
+/**
+ * Handle for a ticket iterator operation
+ */
+struct GNUNET_RECLAIM_TicketIterator
+{
+
+  /**
+   * Kept in a DLL.
+   */
+  struct GNUNET_RECLAIM_TicketIterator *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct GNUNET_RECLAIM_TicketIterator *prev;
+
+  /**
+   * Main handle to access the idp.
+   */
+  struct GNUNET_RECLAIM_Handle *h;
+
+  /**
+   * Function to call on completion.
+   */
+  GNUNET_SCHEDULER_TaskCallback finish_cb;
+
+  /**
+   * Closure for @e error_cb.
+   */
+  void *finish_cb_cls;
+
+  /**
+   * The continuation to call with the results
+   */
+  GNUNET_RECLAIM_TicketCallback tr_cb;
+
+  /**
+   * Closure for @e tr_cb.
+   */
+  void *cls;
+
+  /**
+   * Function to call on errors.
+   */
+  GNUNET_SCHEDULER_TaskCallback error_cb;
+
+  /**
+   * Closure for @e error_cb.
+   */
+  void *error_cb_cls;
+
+  /**
+   * Envelope of the message to send to the service, if not yet
+   * sent.
+   */
+  struct GNUNET_MQ_Envelope *env;
+
+  /**
+   * The operation id this zone iteration operation has
+   */
+  uint32_t r_id;
+
+};
+
+
+/**
+ * Handle for a attribute iterator operation
+ */
+struct GNUNET_RECLAIM_AttributeIterator
+{
+
+  /**
+   * Kept in a DLL.
+   */
+  struct GNUNET_RECLAIM_AttributeIterator *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct GNUNET_RECLAIM_AttributeIterator *prev;
+
+  /**
+   * Main handle to access the idp.
+   */
+  struct GNUNET_RECLAIM_Handle *h;
+
+  /**
+   * Function to call on completion.
+   */
+  GNUNET_SCHEDULER_TaskCallback finish_cb;
+
+  /**
+   * Closure for @e error_cb.
+   */
+  void *finish_cb_cls;
+
+  /**
+   * The continuation to call with the results
+   */
+  GNUNET_RECLAIM_AttributeResult proc;
+
+  /**
+   * Closure for @e proc.
+   */
+  void *proc_cls;
+
+  /**
+   * Function to call on errors.
+   */
+  GNUNET_SCHEDULER_TaskCallback error_cb;
+
+  /**
+   * Closure for @e error_cb.
+   */
+  void *error_cb_cls;
+
+  /**
+   * Envelope of the message to send to the service, if not yet
+   * sent.
+   */
+  struct GNUNET_MQ_Envelope *env;
+
+  /**
+   * Private key of the zone.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * The operation id this zone iteration operation has
+   */
+  uint32_t r_id;
+
+};
+
+
+/**
+ * Handle for the service.
+ */
+struct GNUNET_RECLAIM_Handle
+{
+  /**
+   * Configuration to use.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Socket (if available).
+   */
+  struct GNUNET_CLIENT_Connection *client;
+
+  /**
+   * Closure for 'cb'.
+   */
+  void *cb_cls;
+
+  /**
+   * Head of active operations.
+   */
+  struct GNUNET_RECLAIM_Operation *op_head;
+
+  /**
+   * Tail of active operations.
+   */
+  struct GNUNET_RECLAIM_Operation *op_tail;
+
+  /**
+   * Head of active iterations
+   */
+  struct GNUNET_RECLAIM_AttributeIterator *it_head;
+
+  /**
+   * Tail of active iterations
+   */
+  struct GNUNET_RECLAIM_AttributeIterator *it_tail;
+
+  /**
+   * Head of active iterations
+   */
+  struct GNUNET_RECLAIM_TicketIterator *ticket_it_head;
+
+  /**
+   * Tail of active iterations
+   */
+  struct GNUNET_RECLAIM_TicketIterator *ticket_it_tail;
+
+
+  /**
+   * Currently pending transmission request, or NULL for none.
+   */
+  struct GNUNET_CLIENT_TransmitHandle *th;
+
+  /**
+   * Task doing exponential back-off trying to reconnect.
+   */
+  struct GNUNET_SCHEDULER_Task * reconnect_task;
+
+  /**
+   * Time for next connect retry.
+   */
+  struct GNUNET_TIME_Relative reconnect_backoff;
+
+  /**
+   * Connection to service (if available).
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Request Id generator.  Incremented by one for each request.
+   */
+  uint32_t r_id_gen;
+
+  /**
+   * Are we polling for incoming messages right now?
+   */
+  int in_receive;
+
+};
+
+/**
+ * Try again to connect to the service.
+ *
+ * @param h handle to the reclaim service.
+ */
+static void
+reconnect (struct GNUNET_RECLAIM_Handle *h);
+
+/**
+ * Reconnect
+ *
+ * @param cls the handle
+ */
+static void
+reconnect_task (void *cls)
+{
+  struct GNUNET_RECLAIM_Handle *handle = cls;
+
+  handle->reconnect_task = NULL;
+  reconnect (handle);
+}
+
+
+/**
+ * Disconnect from service and then reconnect.
+ *
+ * @param handle our service
+ */
+static void
+force_reconnect (struct GNUNET_RECLAIM_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);
+}
+
+/**
+ * Free @a it.
+ *
+ * @param it entry to free
+ */
+static void
+free_it (struct GNUNET_RECLAIM_AttributeIterator *it)
+{
+  struct GNUNET_RECLAIM_Handle *h = it->h;
+
+  GNUNET_CONTAINER_DLL_remove (h->it_head,
+                               h->it_tail,
+                               it);
+  if (NULL != it->env)
+    GNUNET_MQ_discard (it->env);
+  GNUNET_free (it);
+}
+
+static void
+free_op (struct GNUNET_RECLAIM_Operation* op)
+{
+  if (NULL == op)
+    return;
+  if (NULL != op->env)
+    GNUNET_MQ_discard (op->env);
+  GNUNET_free(op);
+}
+
+
+/**
+ * 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_GNS_Handle *`
+ * @param error error code
+ */
+static void
+mq_error_handler (void *cls,
+                  enum GNUNET_MQ_Error error)
+{
+  struct GNUNET_RECLAIM_Handle *handle = cls;
+  force_reconnect (handle);
+}
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_attribute_store_response (void *cls,
+                             const struct AttributeStoreResultMessage *msg)
+{
+  struct GNUNET_RECLAIM_Handle *h = cls;
+  struct GNUNET_RECLAIM_Operation *op;
+  uint32_t r_id = ntohl (msg->id);
+  int res;
+  const char *emsg;
+
+  for (op = h->op_head; NULL != op; op = op->next)
+    if (op->r_id == r_id)
+      break;
+  if (NULL == op)
+    return;
+
+  res = ntohl (msg->op_result);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received ATTRIBUTE_STORE_RESPONSE with result %d\n",
+       res);
+
+  /* TODO: add actual error message to response... */
+  if (GNUNET_SYSERR == res)
+    emsg = _("failed to store record\n");
+  else
+    emsg = NULL;
+  if (NULL != op->as_cb)
+    op->as_cb (op->cls,
+              res,
+              emsg);
+  GNUNET_CONTAINER_DLL_remove (h->op_head,
+                               h->op_tail,
+                               op);
+  free_op (op);
+
+}
+
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static int
+check_consume_ticket_result (void *cls,
+                             const struct ConsumeTicketResultMessage *msg)
+{
+  size_t msg_len;
+  size_t attrs_len;
+
+  msg_len = ntohs (msg->header.size);
+  attrs_len = ntohs (msg->attrs_len);
+  if (msg_len != sizeof (struct ConsumeTicketResultMessage) + attrs_len)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_consume_ticket_result (void *cls,
+                              const struct ConsumeTicketResultMessage *msg)
+{
+  struct GNUNET_RECLAIM_Handle *h = cls;
+  struct GNUNET_RECLAIM_Operation *op;
+  size_t attrs_len;
+  uint32_t r_id = ntohl (msg->id);
+
+  attrs_len = ntohs (msg->attrs_len);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Processing attribute result.\n");
+
+
+  for (op = h->op_head; NULL != op; op = op->next)
+    if (op->r_id == r_id)
+      break;
+  if (NULL == op)
+    return;
+
+  {
+    struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
+    struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+    attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char*)&msg[1],
+                                        attrs_len);
+    if (NULL != op->ar_cb)
+    {
+      if (NULL == attrs)
+      {
+        op->ar_cb (op->cls,
+                   &msg->identity,
+                   NULL);
+      }
+      else
+      {
+        for (le = attrs->list_head; NULL != le; le = le->next)
+          op->ar_cb (op->cls,
+                     &msg->identity,
+                     le->claim);
+        GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
+      }
+    }
+    if (NULL != op)
+    {
+      op->ar_cb (op->cls,
+                 NULL,
+                 NULL);
+      GNUNET_CONTAINER_DLL_remove (h->op_head,
+                                   h->op_tail,
+                                   op);
+      free_op (op);
+    }
+    return;
+  }
+  GNUNET_assert (0);
+}
+
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static int
+check_attribute_result (void *cls,
+                        const struct AttributeResultMessage *msg)
+{
+  size_t msg_len;
+  size_t attr_len;
+
+  msg_len = ntohs (msg->header.size);
+  attr_len = ntohs (msg->attr_len);
+  if (msg_len != sizeof (struct AttributeResultMessage) + attr_len)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_attribute_result (void *cls,
+                         const struct AttributeResultMessage *msg)
+{
+  static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
+  struct GNUNET_RECLAIM_Handle *h = cls;
+  struct GNUNET_RECLAIM_AttributeIterator *it;
+  struct GNUNET_RECLAIM_Operation *op;
+  size_t attr_len;
+  uint32_t r_id = ntohl (msg->id);
+
+  attr_len = ntohs (msg->attr_len);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Processing attribute result.\n");
+
+
+  for (it = h->it_head; NULL != it; it = it->next)
+    if (it->r_id == r_id)
+      break;
+  for (op = h->op_head; NULL != op; op = op->next)
+    if (op->r_id == r_id)
+      break;
+  if ((NULL == it) && (NULL == op))
+    return;
+
+  if ( (0 == (memcmp (&msg->identity,
+                      &identity_dummy,
+                      sizeof (identity_dummy)))) )
+  {
+    if ((NULL == it) && (NULL == op))
+    {
+      GNUNET_break (0);
+      force_reconnect (h);
+      return;
+    }
+    if (NULL != it)
+    {
+      if (NULL != it->finish_cb)
+        it->finish_cb (it->finish_cb_cls);
+      free_it (it);
+    }
+    if (NULL != op)
+    {
+      if (NULL != op->ar_cb)
+        op->ar_cb (op->cls,
+                   NULL,
+                   NULL);
+      GNUNET_CONTAINER_DLL_remove (h->op_head,
+                                   h->op_tail,
+                                   op);
+      free_op (op);
+
+    }
+    return;
+  }
+
+  {
+    struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
+    attr = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char*)&msg[1],
+                                                  attr_len);
+    if (NULL != it)
+    {
+      if (NULL != it->proc)
+        it->proc (it->proc_cls,
+                  &msg->identity,
+                  attr);
+    } else if (NULL != op)
+    {
+      if (NULL != op->ar_cb)
+        op->ar_cb (op->cls,
+                   &msg->identity,
+                   attr);
+
+    }
+    GNUNET_free (attr);
+    return;
+  }
+  GNUNET_assert (0);
+}
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static int
+check_ticket_result (void *cls,
+                     const struct TicketResultMessage *msg)
+{
+  size_t msg_len;
+
+  msg_len = ntohs (msg->header.size);
+  if (msg_len < sizeof (struct TicketResultMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_ticket_result (void *cls,
+                      const struct TicketResultMessage *msg)
+{
+  struct GNUNET_RECLAIM_Handle *handle = cls;
+  struct GNUNET_RECLAIM_Operation *op;
+  struct GNUNET_RECLAIM_TicketIterator *it;
+  const struct GNUNET_RECLAIM_Ticket *ticket;
+  uint32_t r_id = ntohl (msg->id);
+  size_t msg_len;
+
+  for (op = handle->op_head; NULL != op; op = op->next)
+    if (op->r_id == r_id)
+      break;
+  for (it = handle->ticket_it_head; NULL != it; it = it->next)
+    if (it->r_id == r_id)
+      break;
+  if ((NULL == op) && (NULL == it))
+    return;
+  msg_len = ntohs (msg->header.size);
+  if (NULL != op)
+  {
+    GNUNET_CONTAINER_DLL_remove (handle->op_head,
+                                 handle->op_tail,
+                                 op);
+    if (msg_len == sizeof (struct TicketResultMessage))
+    {
+      if (NULL != op->tr_cb)
+        op->tr_cb (op->cls, NULL);
+    } else {
+      ticket = (struct GNUNET_RECLAIM_Ticket *)&msg[1];
+      if (NULL != op->tr_cb)
+        op->tr_cb (op->cls, ticket);
+    }
+    free_op (op);
+    return;
+  } else if (NULL != it) {
+    if (msg_len == sizeof (struct TicketResultMessage))
+    {
+      if (NULL != it->tr_cb)
+        GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head,
+                                     handle->ticket_it_tail,
+                                     it);
+      it->finish_cb (it->finish_cb_cls);
+      GNUNET_free (it);
+    } else {
+      ticket = (struct GNUNET_RECLAIM_Ticket *)&msg[1];
+      if (NULL != it->tr_cb)
+        it->tr_cb (it->cls, ticket);
+    }
+    return;
+  }
+  GNUNET_break (0);
+}
+
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_revoke_ticket_result (void *cls,
+                             const struct RevokeTicketResultMessage *msg)
+{
+  struct GNUNET_RECLAIM_Handle *h = cls;
+  struct GNUNET_RECLAIM_Operation *op;
+  uint32_t r_id = ntohl (msg->id);
+  int32_t success;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Processing revocation result.\n");
+
+
+  for (op = h->op_head; NULL != op; op = op->next)
+    if (op->r_id == r_id)
+      break;
+  if (NULL == op)
+    return;
+  success = ntohl (msg->success);
+  {
+    if (NULL != op->rvk_cb)
+    {
+      op->rvk_cb (op->cls,
+                  success,
+                  NULL);
+    }
+    GNUNET_CONTAINER_DLL_remove (h->op_head,
+                                 h->op_tail,
+                                 op);
+    free_op (op);
+    return;
+  }
+  GNUNET_assert (0);
+}
+
+
+
+/**
+ * Try again to connect to the service.
+ *
+ * @param h handle to the reclaim service.
+ */
+static void
+reconnect (struct GNUNET_RECLAIM_Handle *h)
+{
+  struct GNUNET_MQ_MessageHandler handlers[] = {
+    GNUNET_MQ_hd_fixed_size (attribute_store_response,
+                             GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE_RESPONSE,
+                             struct AttributeStoreResultMessage,
+                             h),
+    GNUNET_MQ_hd_var_size (attribute_result,
+                           GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT,
+                           struct AttributeResultMessage,
+                           h),
+    GNUNET_MQ_hd_var_size (ticket_result,
+                           GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT,
+                           struct TicketResultMessage,
+                           h),
+    GNUNET_MQ_hd_var_size (consume_ticket_result,
+                           GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT,
+                           struct ConsumeTicketResultMessage,
+                           h),
+    GNUNET_MQ_hd_fixed_size (revoke_ticket_result,
+                             GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT,
+                             struct RevokeTicketResultMessage,
+                             h),
+    GNUNET_MQ_handler_end ()
+  };
+  struct GNUNET_RECLAIM_Operation *op;
+
+  GNUNET_assert (NULL == h->mq);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Connecting to reclaim service.\n");
+
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
+                                 "reclaim",
+                                 handlers,
+                                 &mq_error_handler,
+                                 h);
+  if (NULL == h->mq)
+    return;
+  for (op = h->op_head; NULL != op; op = op->next)
+    GNUNET_MQ_send_copy (h->mq,
+                         op->env);
+}
+
+
+/**
+ * Connect to the reclaim service.
+ *
+ * @param cfg the configuration to use
+ * @return handle to use
+ */
+struct GNUNET_RECLAIM_Handle *
+GNUNET_RECLAIM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_RECLAIM_Handle *h;
+
+  h = GNUNET_new (struct GNUNET_RECLAIM_Handle);
+  h->cfg = cfg;
+  reconnect (h);
+  if (NULL == h->mq)
+  {
+    GNUNET_free (h);
+    return NULL;
+  }
+  return h;
+}
+
+
+/**
+ * Cancel an operation. Note that the operation MAY still
+ * be executed; this merely cancels the continuation; if the request
+ * was already transmitted, the service may still choose to complete
+ * the operation.
+ *
+ * @param op operation to cancel
+ */
+void
+GNUNET_RECLAIM_cancel (struct GNUNET_RECLAIM_Operation *op)
+{
+  struct GNUNET_RECLAIM_Handle *h = op->h;
+
+  GNUNET_CONTAINER_DLL_remove (h->op_head,
+                               h->op_tail,
+                               op);
+  free_op (op);
+}
+
+
+/**
+ * Disconnect from service
+ *
+ * @param h handle to destroy
+ */
+void
+GNUNET_RECLAIM_disconnect (struct GNUNET_RECLAIM_Handle *h)
+{
+  GNUNET_assert (NULL != h);
+  if (NULL != h->mq)
+  {
+    GNUNET_MQ_destroy (h->mq);
+    h->mq = NULL;
+  }
+  if (NULL != h->reconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (h->reconnect_task);
+    h->reconnect_task = NULL;
+  }
+  GNUNET_assert (NULL == h->op_head);
+  GNUNET_free (h);
+}
+
+/**
+ * Store an attribute.  If the attribute is already present,
+ * it is replaced with the new attribute.
+ *
+ * @param h handle to the reclaim
+ * @param pkey private key of the identity
+ * @param attr the attribute value
+ * @param exp_interval the relative expiration interval for the attribute
+ * @param cont continuation to call when done
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the request
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_attribute_store (struct GNUNET_RECLAIM_Handle *h,
+                                          const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+                                          const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
+                                          const struct GNUNET_TIME_Relative *exp_interval,
+                                          GNUNET_RECLAIM_ContinuationWithStatus cont,
+                                          void *cont_cls)
+{
+  struct GNUNET_RECLAIM_Operation *op;
+  struct AttributeStoreMessage *sam;
+  size_t attr_len;
+
+  op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
+  op->h = h;
+  op->as_cb = cont;
+  op->cls = cont_cls;
+  op->r_id = h->r_id_gen++;
+  GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
+                                    h->op_tail,
+                                    op);
+  attr_len = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (attr);
+  op->env = GNUNET_MQ_msg_extra (sam,
+                                 attr_len,
+                                 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE);
+  sam->identity = *pkey;
+  sam->id = htonl (op->r_id);
+  sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
+
+  GNUNET_RECLAIM_ATTRIBUTE_serialize (attr,
+                                       (char*)&sam[1]);
+
+  sam->attr_len = htons (attr_len);
+  if (NULL != h->mq)
+    GNUNET_MQ_send_copy (h->mq,
+                         op->env);
+  return op;
+
+}
+
+
+/**
+ * List all attributes for a local identity.
+ * This MUST lock the `struct GNUNET_RECLAIM_Handle`
+ * for any other calls than #GNUNET_RECLAIM_get_attributes_next() and
+ * #GNUNET_RECLAIM_get_attributes_stop. @a proc will be called once
+ * immediately, and then again after
+ * #GNUNET_RECLAIM_get_attributes_next() is invoked.
+ *
+ * On error (disconnect), @a error_cb will be invoked.
+ * On normal completion, @a finish_cb proc will be
+ * invoked.
+ *
+ * @param h handle to the idp
+ * @param identity identity to access
+ * @param error_cb function to call on error (i.e. disconnect),
+ *        the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each attribute; it
+ *        will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ *        the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
+ */
+struct GNUNET_RECLAIM_AttributeIterator *
+GNUNET_RECLAIM_get_attributes_start (struct GNUNET_RECLAIM_Handle *h,
+                                               const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                               GNUNET_SCHEDULER_TaskCallback error_cb,
+                                               void *error_cb_cls,
+                                               GNUNET_RECLAIM_AttributeResult proc,
+                                               void *proc_cls,
+                                               GNUNET_SCHEDULER_TaskCallback finish_cb,
+                                               void *finish_cb_cls)
+{
+  struct GNUNET_RECLAIM_AttributeIterator *it;
+  struct GNUNET_MQ_Envelope *env;
+  struct AttributeIterationStartMessage *msg;
+  uint32_t rid;
+
+  rid = h->r_id_gen++;
+  it = GNUNET_new (struct GNUNET_RECLAIM_AttributeIterator);
+  it->h = h;
+  it->error_cb = error_cb;
+  it->error_cb_cls = error_cb_cls;
+  it->finish_cb = finish_cb;
+  it->finish_cb_cls = finish_cb_cls;
+  it->proc = proc;
+  it->proc_cls = proc_cls;
+  it->r_id = rid;
+  it->identity = *identity;
+  GNUNET_CONTAINER_DLL_insert_tail (h->it_head,
+                                    h->it_tail,
+                                    it);
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START);
+  msg->id = htonl (rid);
+  msg->identity = *identity;
+  if (NULL == h->mq)
+    it->env = env;
+  else
+    GNUNET_MQ_send (h->mq,
+                    env);
+  return it;
+}
+
+
+/**
+ * Calls the record processor specified in #GNUNET_RECLAIM_get_attributes_start
+ * for the next record.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_RECLAIM_get_attributes_next (struct GNUNET_RECLAIM_AttributeIterator *it)
+{
+  struct GNUNET_RECLAIM_Handle *h = it->h;
+  struct AttributeIterationNextMessage *msg;
+  struct GNUNET_MQ_Envelope *env;
+
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT);
+  msg->id = htonl (it->r_id);
+  GNUNET_MQ_send (h->mq,
+                  env);
+}
+
+
+/**
+ * Stops iteration and releases the idp handle for further calls.  Must
+ * be called on any iteration that has not yet completed prior to calling
+ * #GNUNET_RECLAIM_disconnect.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it)
+{
+  struct GNUNET_RECLAIM_Handle *h = it->h;
+  struct GNUNET_MQ_Envelope *env;
+  struct AttributeIterationStopMessage *msg;
+
+  if (NULL != h->mq)
+  {
+    env = GNUNET_MQ_msg (msg,
+                         GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP);
+    msg->id = htonl (it->r_id);
+    GNUNET_MQ_send (h->mq,
+                    env);
+  }
+  free_it (it);
+}
+
+
+/** TODO
+ * Issues a ticket to another identity. The identity may use
+ * @GNUNET_RECLAIM_authorization_ticket_consume to consume the ticket
+ * and retrieve the attributes specified in the AttributeList.
+ *
+ * @param h the reclaim to use
+ * @param iss the issuing identity
+ * @param rp the subject of the ticket (the relying party)
+ * @param attrs the attributes that the relying party is given access to
+ * @param cb the callback
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_ticket_issue (struct GNUNET_RECLAIM_Handle *h,
+                                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
+                                       const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
+                                       const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+                                       GNUNET_RECLAIM_TicketCallback cb,
+                                       void *cb_cls)
+{
+  struct GNUNET_RECLAIM_Operation *op;
+  struct IssueTicketMessage *tim;
+  size_t attr_len;
+
+  op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
+  op->h = h;
+  op->tr_cb = cb;
+  op->cls = cb_cls;
+  op->r_id = h->r_id_gen++;
+  GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
+                                    h->op_tail,
+                                    op);
+  attr_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
+  op->env = GNUNET_MQ_msg_extra (tim,
+                                 attr_len,
+                                 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET);
+  tim->identity = *iss;
+  tim->rp = *rp;
+  tim->id = htonl (op->r_id);
+
+  GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs,
+                                            (char*)&tim[1]);
+
+  tim->attr_len = htons (attr_len);
+  if (NULL != h->mq)
+    GNUNET_MQ_send_copy (h->mq,
+                         op->env);
+  return op;
+}
+
+/**
+ * Consumes an issued ticket. The ticket is persisted
+ * and used to retrieve identity information from the issuer
+ *
+ * @param h the reclaim to use
+ * @param identity the identity that is the subject of the issued ticket (the relying party)
+ * @param ticket the issued ticket to consume
+ * @param cb the callback to call
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_ticket_consume (struct GNUNET_RECLAIM_Handle *h,
+                                         const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                         const struct GNUNET_RECLAIM_Ticket *ticket,
+                                         GNUNET_RECLAIM_AttributeResult cb,
+                                         void *cb_cls)
+{
+  struct GNUNET_RECLAIM_Operation *op;
+  struct ConsumeTicketMessage *ctm;
+
+  op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
+  op->h = h;
+  op->ar_cb = cb;
+  op->cls = cb_cls;
+  op->r_id = h->r_id_gen++;
+  GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
+                                    h->op_tail,
+                                    op);
+  op->env = GNUNET_MQ_msg_extra (ctm,
+                                 sizeof (const struct GNUNET_RECLAIM_Ticket),
+                                 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET);
+  ctm->identity = *identity;
+  ctm->id = htonl (op->r_id);
+
+  GNUNET_memcpy ((char*)&ctm[1],
+                 ticket,
+                 sizeof (const struct GNUNET_RECLAIM_Ticket));
+
+  if (NULL != h->mq)
+    GNUNET_MQ_send_copy (h->mq,
+                         op->env);
+  return op;
+
+}
+
+
+/**
+ * Lists all tickets that have been issued to remote
+ * identites (relying parties)
+ *
+ * @param h the reclaim to use
+ * @param identity the issuing identity
+ * @param error_cb function to call on error (i.e. disconnect),
+ *        the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each ticket; it
+ *        will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ *        the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
+ */
+struct GNUNET_RECLAIM_TicketIterator *
+GNUNET_RECLAIM_ticket_iteration_start (struct GNUNET_RECLAIM_Handle *h,
+                                                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                                 GNUNET_SCHEDULER_TaskCallback error_cb,
+                                                 void *error_cb_cls,
+                                                 GNUNET_RECLAIM_TicketCallback proc,
+                                                 void *proc_cls,
+                                                 GNUNET_SCHEDULER_TaskCallback finish_cb,
+                                                 void *finish_cb_cls)
+{
+  struct GNUNET_RECLAIM_TicketIterator *it;
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
+  struct GNUNET_MQ_Envelope *env;
+  struct TicketIterationStartMessage *msg;
+  uint32_t rid;
+
+  GNUNET_CRYPTO_ecdsa_key_get_public (identity,
+                                      &identity_pub);
+  rid = h->r_id_gen++;
+  it = GNUNET_new (struct GNUNET_RECLAIM_TicketIterator);
+  it->h = h;
+  it->error_cb = error_cb;
+  it->error_cb_cls = error_cb_cls;
+  it->finish_cb = finish_cb;
+  it->finish_cb_cls = finish_cb_cls;
+  it->tr_cb = proc;
+  it->cls = proc_cls;
+  it->r_id = rid;
+  GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head,
+                                    h->ticket_it_tail,
+                                    it);
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START);
+  msg->id = htonl (rid);
+  msg->identity = identity_pub;
+  msg->is_audience = htonl (GNUNET_NO);
+  if (NULL == h->mq)
+    it->env = env;
+  else
+    GNUNET_MQ_send (h->mq,
+                    env);
+  return it;
+
+}
+
+
+/**
+ * Lists all tickets that have been issued to remote
+ * identites (relying parties)
+ *
+ * @param h the reclaim to use
+ * @param identity the issuing identity
+ * @param error_cb function to call on error (i.e. disconnect),
+ *        the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each ticket; it
+ *        will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ *        the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
+ */
+struct GNUNET_RECLAIM_TicketIterator *
+GNUNET_RECLAIM_ticket_iteration_start_rp (struct GNUNET_RECLAIM_Handle *h,
+                                                    const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+                                                    GNUNET_SCHEDULER_TaskCallback error_cb,
+                                                    void *error_cb_cls,
+                                                    GNUNET_RECLAIM_TicketCallback proc,
+                                                    void *proc_cls,
+                                                    GNUNET_SCHEDULER_TaskCallback finish_cb,
+                                                    void *finish_cb_cls)
+{
+  struct GNUNET_RECLAIM_TicketIterator *it;
+  struct GNUNET_MQ_Envelope *env;
+  struct TicketIterationStartMessage *msg;
+  uint32_t rid;
+
+  rid = h->r_id_gen++;
+  it = GNUNET_new (struct GNUNET_RECLAIM_TicketIterator);
+  it->h = h;
+  it->error_cb = error_cb;
+  it->error_cb_cls = error_cb_cls;
+  it->finish_cb = finish_cb;
+  it->finish_cb_cls = finish_cb_cls;
+  it->tr_cb = proc;
+  it->cls = proc_cls;
+  it->r_id = rid;
+  GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head,
+                                    h->ticket_it_tail,
+                                    it);
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START);
+  msg->id = htonl (rid);
+  msg->identity = *identity;
+  msg->is_audience = htonl (GNUNET_YES);
+  if (NULL == h->mq)
+    it->env = env;
+  else
+    GNUNET_MQ_send (h->mq,
+                    env);
+  return it;
+
+
+}
+
+/**
+ * Calls the record processor specified in #GNUNET_RECLAIM_ticket_iteration_start
+ * for the next record.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_RECLAIM_ticket_iteration_next (struct GNUNET_RECLAIM_TicketIterator *it)
+{
+  struct GNUNET_RECLAIM_Handle *h = it->h;
+  struct TicketIterationNextMessage *msg;
+  struct GNUNET_MQ_Envelope *env;
+
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT);
+  msg->id = htonl (it->r_id);
+  GNUNET_MQ_send (h->mq,
+                  env);
+}
+
+
+/**
+ * Stops iteration and releases the idp handle for further calls.  Must
+ * be called on any iteration that has not yet completed prior to calling
+ * #GNUNET_RECLAIM_disconnect.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_RECLAIM_ticket_iteration_stop (struct GNUNET_RECLAIM_TicketIterator *it)
+{
+  struct GNUNET_RECLAIM_Handle *h = it->h;
+  struct GNUNET_MQ_Envelope *env;
+  struct TicketIterationStopMessage *msg;
+
+  if (NULL != h->mq)
+  {
+    env = GNUNET_MQ_msg (msg,
+                         GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP);
+    msg->id = htonl (it->r_id);
+    GNUNET_MQ_send (h->mq,
+                    env);
+  }
+  GNUNET_free (it);
+}
+
+/**
+ * Revoked an issued ticket. The relying party will be unable to retrieve
+ * updated attributes.
+ *
+ * @param h the reclaim to use
+ * @param identity the issuing identity
+ * @param ticket the ticket to revoke
+ * @param cb the callback
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_ticket_revoke (struct GNUNET_RECLAIM_Handle *h,
+                                        const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                        const struct GNUNET_RECLAIM_Ticket *ticket,
+                                        GNUNET_RECLAIM_ContinuationWithStatus cb,
+                                        void *cb_cls)
+{
+  struct GNUNET_RECLAIM_Operation *op;
+  struct RevokeTicketMessage *msg;
+  uint32_t rid;
+
+  rid = h->r_id_gen++;
+  op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
+  op->h = h;
+  op->rvk_cb = cb;
+  op->cls = cb_cls;
+  op->r_id = rid;
+  GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
+                                    h->op_tail,
+                                    op);
+  op->env = GNUNET_MQ_msg_extra (msg,
+                             sizeof (struct GNUNET_RECLAIM_Ticket),
+                             GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET);
+  msg->id = htonl (rid);
+  msg->identity = *identity;
+  GNUNET_memcpy (&msg[1],
+                 ticket,
+                 sizeof (struct GNUNET_RECLAIM_Ticket));
+  if (NULL != h->mq) {
+    GNUNET_MQ_send (h->mq,
+                    op->env);
+    op->env = NULL;
+  }
+  return op;
+}
+
+
+
+/* end of reclaim_api.c */
diff --git a/src/reclaim/test_reclaim.sh b/src/reclaim/test_reclaim.sh
new file mode 100755 (executable)
index 0000000..311f538
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/bash
+#trap "gnunet-arm -e -c test_reclaim_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_reclaim.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_reclaim.conf
+gnunet-identity -C testego -c test_reclaim.conf
+valgrind gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf
+gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf
+gnunet-reclaim -e testego -D -c test_reclaim.conf
+gnunet-arm -e -c test_reclaim.conf
diff --git a/src/reclaim/test_reclaim_attribute.sh b/src/reclaim/test_reclaim_attribute.sh
new file mode 100755 (executable)
index 0000000..39bd715
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_reclaim.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_reclaim.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_reclaim.conf
+#gnunet-arm -i rest -c test_reclaim.conf
+gnunet-identity -C testego -c test_reclaim.conf
+gnunet-identity -C rpego -c test_reclaim.conf
+TEST_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep testego | awk '{print $3}')
+gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf
+gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf > /dev/null 2>&1
+if test $? != 0
+then
+  echo "Failed."
+  exit 1
+fi
+
+#curl localhost:7776/reclaim/attributes/testego
+gnunet-arm -e -c test_reclaim.conf
diff --git a/src/reclaim/test_reclaim_consume.sh b/src/reclaim/test_reclaim_consume.sh
new file mode 100755 (executable)
index 0000000..36c8052
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_reclaim.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_reclaim.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_reclaim.conf
+#gnunet-arm -i rest -c test_reclaim.conf
+gnunet-identity -C testego -c test_reclaim.conf
+gnunet-identity -C rpego -c test_reclaim.conf
+SUBJECT_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep rpego | awk '{print $3}')
+TEST_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep testego | awk '{print $3}')
+gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf
+gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf
+TICKET=$(gnunet-reclaim -e testego -i "email,name" -r $SUBJECT_KEY -c test_reclaim.conf | awk '{print $1}')
+gnunet-reclaim -e rpego -C $TICKET -c test_reclaim.conf > /dev/null 2>&1
+
+if test $? != 0
+then
+  "Failed."
+  exit 1
+fi
+#curl http://localhost:7776/reclaim/tickets/testego
+gnunet-arm -e -c test_reclaim.conf
diff --git a/src/reclaim/test_reclaim_defaults.conf b/src/reclaim/test_reclaim_defaults.conf
new file mode 100644 (file)
index 0000000..a9a197d
--- /dev/null
@@ -0,0 +1,24 @@
+@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
+
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-idp-testing/
+
+[namestore-sqlite]
+FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
+
+[namecache-sqlite]
+FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db
+
+[identity]
+# Directory where we store information about our egos
+EGODIR = $GNUNET_TEST_HOME/identity/egos/
+
+[dhtcache]
+DATABASE = heap
+
+[transport]
+PLUGINS = tcp
+
+[transport-tcp]
+BINDTO = 127.0.0.1
+
diff --git a/src/reclaim/test_reclaim_issue.sh b/src/reclaim/test_reclaim_issue.sh
new file mode 100755 (executable)
index 0000000..6a71470
--- /dev/null
@@ -0,0 +1,42 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_reclaim.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_reclaim.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_reclaim.conf
+#gnunet-arm -i rest -c test_reclaim.conf
+gnunet-identity -C testego -c test_reclaim.conf
+gnunet-identity -C rpego -c test_reclaim.conf
+SUBJECT_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep rpego | awk '{print $3}')
+TEST_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep testego | awk '{print $3}')
+gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf > /dev/null 2>&1
+gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf > /dev/null 2>&1
+#gnunet-reclaim -e testego -D -c test_reclaim.conf
+gnunet-reclaim -e testego -i "email,name" -r $SUBJECT_KEY -c test_reclaim.conf > /dev/null 2>&1
+if test $? != 0
+then
+  echo "Failed."
+  exit 1
+fi
+#curl http://localhost:7776/reclaim/attributes/testego
+gnunet-arm -e -c test_reclaim.conf
diff --git a/src/reclaim/test_reclaim_revoke.sh b/src/reclaim/test_reclaim_revoke.sh
new file mode 100755 (executable)
index 0000000..595752f
--- /dev/null
@@ -0,0 +1,65 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_reclaim.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_reclaim.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_reclaim.conf 2&>1 > /dev/null
+gnunet-identity -C alice -c test_reclaim.conf
+gnunet-identity -C bob -c test_reclaim.conf
+gnunet-identity -C eve -c test_reclaim.conf
+ALICE_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep alice | awk '{print $3}')
+BOB_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep bob | awk '{print $3}')
+EVE_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep eve | awk '{print $3}')
+
+gnunet-reclaim -e alice -E 15s -a email -V john@doe.gnu -c test_reclaim.conf 
+gnunet-reclaim -e alice -E 15s -a name -V John -c test_reclaim.conf
+TICKET_BOB=$(gnunet-reclaim -e alice -i "email,name" -r $BOB_KEY -c test_reclaim.conf | awk '{print $1}')
+#gnunet-reclaim -e bob -C $TICKET_BOB -c test_reclaim.conf
+TICKET_EVE=$(gnunet-reclaim -e alice -i "email" -r $EVE_KEY -c test_reclaim.conf | awk '{print $1}')
+
+#echo "Consuming $TICKET"
+#gnunet-reclaim -e eve -C $TICKET_EVE -c test_reclaim.conf
+gnunet-reclaim -e alice -R $TICKET_EVE -c test_reclaim.conf
+
+#sleep 6
+
+gnunet-reclaim -e eve -C $TICKET_EVE -c test_reclaim.conf 2&>1 >/dev/null
+if test $? == 0
+then 
+  echo "Eve can still resolve attributes..."
+  gnunet-arm -e -c test_reclaim.conf
+  exit 1
+fi
+
+gnunet-arm -e -c test_reclaim.conf
+gnunet-arm -s -c test_reclaim.conf 2&>1 > /dev/null
+
+gnunet-reclaim -e bob -C $TICKET_BOB -c test_reclaim.conf 2&>1 >/dev/null
+if test $? != 0
+then
+  echo "Bob cannot resolve attributes..."
+  gnunet-arm -e -c test_reclaim.conf
+  exit 1
+fi
+
+gnunet-arm -e -c test_reclaim.conf