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
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
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
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 += \
+++ /dev/null
-# 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)
-
-
+++ /dev/null
-/*
- 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 */
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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 */
+++ /dev/null
-gnunet-service-identity-provider
-gnunet-identity-token
+++ /dev/null
-# 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
+++ /dev/null
-/*
- 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;
-}
+++ /dev/null
-/*
- 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 */
+++ /dev/null
-[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
+++ /dev/null
-[identity-token]
-BINARY=gnunet-service-identity-token
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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 */
+++ /dev/null
-/*
- 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;
-}
+++ /dev/null
-#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
+++ /dev/null
-/*
- 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 */
+++ /dev/null
- /*
- * 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 */
+++ /dev/null
-/*
- 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 */
+++ /dev/null
-/*
- 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,
- ¤t_zone_pkey);
-
- if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey,
- sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
- {
- if ( 0 == memcmp (&login_identity_pkey, ¤t_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 */
+++ /dev/null
-@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
+++ /dev/null
-#!/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
+++ /dev/null
-#!/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
+++ /dev/null
-#!/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
+++ /dev/null
-@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
-
+++ /dev/null
-#!/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
+++ /dev/null
-#!/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
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 \
+++ /dev/null
-/*
- 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 */
+++ /dev/null
-/*
- This file is part of GNUnet
- Copyright (C) 2012, 2013 GNUnet e.V.
-
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU 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 */
+++ /dev/null
-/*
- This file is part of GNUnet
- Copyright (C) 2012, 2013 GNUnet e.V.
-
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU 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 */
+++ /dev/null
-/*
- 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 */
*
* 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
/**************************************************
*
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ This file is part of GNUnet
+ Copyright (C) 2012, 2013 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU 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 */
--- /dev/null
+/*
+ This file is part of GNUnet
+ Copyright (C) 2012, 2013 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU 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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+# 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)
+
+
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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
--- /dev/null
+gnunet-service-identity-provider
+gnunet-identity-token
--- /dev/null
+# 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
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+#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
--- /dev/null
+/*
+ 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 */
--- /dev/null
+ /*
+ * 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 */
--- /dev/null
+/*
+ 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,
+ ¤t_zone_pkey);
+
+ if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey,
+ sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
+ {
+ if ( 0 == memcmp (&login_identity_pkey, ¤t_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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+[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
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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 */
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+@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
+
--- /dev/null
+#!/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
--- /dev/null
+#!/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