- Finish refactoring
authorMartin Schanzenbach <mschanzenbach@posteo.de>
Thu, 7 Jan 2016 21:10:24 +0000 (21:10 +0000)
committerMartin Schanzenbach <mschanzenbach@posteo.de>
Thu, 7 Jan 2016 21:10:24 +0000 (21:10 +0000)
18 files changed:
src/Makefile.am
src/identity-provider/Makefile.am [new file with mode: 0644]
src/identity-provider/gnunet-identity-token.c [new file with mode: 0644]
src/identity-provider/gnunet-service-identity-token.c [new file with mode: 0644]
src/identity-provider/identity-token.c [new file with mode: 0644]
src/identity-provider/identity-token.conf [new file with mode: 0644]
src/identity-provider/plugin_rest_identity_token.c [new file with mode: 0644]
src/identity-token/Makefile.am [deleted file]
src/identity-token/gnunet-identity-token.c [deleted file]
src/identity-token/gnunet-service-identity-token.c [deleted file]
src/identity-token/identity-token.c [deleted file]
src/identity-token/identity-token.conf [deleted file]
src/identity-token/identity-token.h [deleted file]
src/identity-token/plugin_rest_identity_token.c [deleted file]
src/identity/plugin_gnsrecord_identity.c
src/include/gnunet_identity_provider_lib.h [new file with mode: 0644]
src/include/gnunet_signatures.h
src/rest/gnunet-rest-server.c

index 76997918fa8768929c2a80a774e1bba013702fc5..6e0fa5c4b866434162ddc97f67ae2d57dd637d08 100644 (file)
@@ -28,7 +28,7 @@ if HAVE_EXPERIMENTAL
 endif
 
 if HAVE_REST
-       EXP_DIR += identity-token
+       EXP_DIR += identity-provider
 endif
 
 if BUILD_PULSE_HELPERS
diff --git a/src/identity-provider/Makefile.am b/src/identity-provider/Makefile.am
new file mode 100644 (file)
index 0000000..a9338ba
--- /dev/null
@@ -0,0 +1,70 @@
+# 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
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+pkgcfg_DATA = \
+  identity-token.conf
+
+plugin_LTLIBRARIES = \
+       libgnunet_plugin_rest_identity_token.la
+lib_LTLIBRARIES = \
+       libgnunetidentityprovider.la
+
+bin_PROGRAMS = \
+ gnunet-identity-token
+
+libexec_PROGRAMS = \
+ gnunet-service-identity-token
+
+gnunet_service_identity_token_SOURCES = \
+ gnunet-service-identity-token.c
+gnunet_service_identity_token_LDADD = \
+ libgnunetidentityprovider.la \
+ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/identity/libgnunetidentity.la \
+ $(GN_LIBINTL) \
+ -ljansson
+
+libgnunetidentityprovider_la_SOURCES = \
+  identity-token.c
+libgnunetidentityprovider_la_LIBADD = \
+       $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+       $(LTLIBINTL) -ljansson
+
+libgnunet_plugin_rest_identity_token_la_SOURCES = \
+  plugin_rest_identity_token.c
+libgnunet_plugin_rest_identity_token_la_LIBADD = \
+       $(top_builddir)/src/identity/libgnunetidentity.la \
+       $(top_builddir)/src/rest/libgnunetrest.la \
+       $(top_builddir)/src/namestore/libgnunetnamestore.la \
+       $(top_builddir)/src/gns/libgnunetgns.la \
+  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+  $(LTLIBINTL) -ljansson -lmicrohttpd
+libgnunet_plugin_rest_identity_token_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
+gnunet_identity_token_SOURCES = \
+ gnunet-identity-token.c         
+gnunet_identity_token_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  -ljansson -lmicrohttpd \
+  $(GN_LIBINTL)
+
+
diff --git a/src/identity-provider/gnunet-identity-token.c b/src/identity-provider/gnunet-identity-token.c
new file mode 100644 (file)
index 0000000..ad4aae7
--- /dev/null
@@ -0,0 +1,114 @@
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include <jansson.h>
+#include "gnunet_signatures.h"
+
+/**
+ * The token
+ */
+static char* token;
+
+/**
+ * Weather to print the token
+ */
+static int print_token;
+
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  char* payload;
+  char* header;
+  //Get token parts
+  char* header_b64 = strtok (token, ".");
+  char* payload_b64 = strtok(NULL, ".");
+  char* signature_b32 = strtok(NULL, ".");
+  const char* keystring;
+  char* data;
+  json_t *payload_json;
+  json_t *keystring_json;
+  json_error_t error;
+  struct GNUNET_CRYPTO_EcdsaPublicKey key;
+  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
+  struct GNUNET_CRYPTO_EcdsaSignature sig;
+  //Decode payload
+  GNUNET_STRINGS_base64_decode (payload_b64,
+                                strlen (payload_b64),
+                                &payload);
+  //Decode header
+  GNUNET_STRINGS_base64_decode (header_b64,
+                                strlen (header_b64),
+                                &header);
+  if (NULL == token)
+    return;
+  
+
+  GNUNET_asprintf(&data,
+                  "%s,%s",
+                  header_b64,
+                  payload_b64);
+  char *val = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + strlen (data));
+  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose*)val;
+  purpose->size = htonl(sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + strlen (data));
+  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
+  memcpy (&purpose[1], data, strlen(data));
+
+  
+  payload_json = json_loads (payload, 0, &error);
+  if ((NULL == payload_json) || !json_is_object (payload_json))
+  {
+    return;
+  }
+  keystring_json =  json_object_get (payload_json, "iss");
+  if (!json_is_string (keystring_json))
+  {
+    return;
+  }
+  keystring = json_string_value (keystring_json);
+  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (keystring,
+                                                               strlen (keystring),
+                                                               &key))
+  {
+    return;
+  }
+  GNUNET_STRINGS_string_to_data (signature_b32,
+                                strlen (signature_b32),
+                                &sig,
+                                sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+  
+  if (print_token) {
+    printf ("Token:\nHeader:\t\t%s\nPayload:\t%s\nSignature:\t%s\n", header, payload, keystring);
+  }
+  
+  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN,
+                                              purpose,
+                                              &sig,
+                                              &key))
+  {
+    printf("Signature not OK!\n");
+    return;
+  }
+  printf("Signature OK!\n");
+  return;
+}
+int
+main(int argc, char *const argv[])
+{
+  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+    {'t', "token", NULL,
+      gettext_noop ("GNUid token"), 1,
+      &GNUNET_GETOPT_set_string, &token},
+    {'p', "print", NULL,
+      gettext_noop ("Print token contents"), 0,
+      &GNUNET_GETOPT_set_one, &print_token},
+
+    GNUNET_GETOPT_OPTION_END
+  };
+  return GNUNET_PROGRAM_run (argc, argv, "ct",
+                             "ct", options,
+                             &run, NULL);
+}
+
+
diff --git a/src/identity-provider/gnunet-service-identity-token.c b/src/identity-provider/gnunet-service-identity-token.c
new file mode 100644 (file)
index 0000000..039d1c7
--- /dev/null
@@ -0,0 +1,762 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 Christian Grothoff (and other contributing authors)
+
+   GNUnet is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNUnet; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @file src/rest/gnunet-service-identity-token.c
+ * @brief Identity Token Service
+ *
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_identity_service.h"
+#include "gnunet_gnsrecord_lib.h"
+#include "gnunet_namestore_service.h"
+#include <jansson.h>
+#include "gnunet_signatures.h"
+#include "gnunet_identity_provider_lib.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
+
+/**
+ * Service state (to detect initial update pass)
+ */
+static int state;
+
+/**
+ * Head of ego entry DLL
+ */
+static struct EgoEntry *ego_head;
+
+/**
+ * Tail of ego entry DLL
+ */
+static struct EgoEntry *ego_tail;
+
+/**
+ * Identity handle
+ */
+static struct GNUNET_IDENTITY_Handle *identity_handle;
+
+/**
+ * Namestore handle
+ */
+static struct GNUNET_NAMESTORE_Handle *ns_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;
+
+/**
+ * Timeout for next update pass
+ */
+static struct GNUNET_TIME_Relative min_rel_exp;
+
+
+/**
+ * Currently processed token
+ */
+static struct GNUNET_IDENTITY_PROVIDER_Token *token;
+
+/**
+ * Label for currently processed token
+ */
+static char* label;
+
+/**
+ * Scopes for processed token
+ */
+static char* scopes;
+
+/**
+ * Expiration for processed token
+ */
+static uint64_t rd_exp;
+
+/**
+ * ECDHE Privkey for processed token metadata
+ */
+static struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_privkey;
+
+/**
+ * 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;
+
+  /**
+   * Attributes are old and should be updated if GNUNET_YES
+   */
+  int attributes_dirty;
+};
+
+/**
+ * Our configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+
+/**
+ * Continuation for token store call
+ *
+ * @param cls NULL
+ * @param success error code
+ * @param emsg error message
+ */
+static void
+store_token_cont (void *cls,
+                  int32_t success,
+                  const char *emsg)
+{
+  ns_qe = NULL;
+  if (GNUNET_SYSERR == success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to update token: %s\n",
+                emsg);
+    return;
+  }
+  GNUNET_NAMESTORE_zone_iterator_next (ns_it);
+}
+
+
+/**
+ * This function updates the old token with new attributes,
+ * removes deleted attributes and expiration times.
+ *
+ * @param cls the ego entry
+ * @param tc task context
+ */
+static void
+handle_token_update (void *cls,
+                     const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  char *token_metadata;
+  char *write_ptr;
+  char *enc_token_str;
+  const char *key;
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
+  struct GNUNET_CRYPTO_EcdhePrivateKey *new_ecdhe_privkey;
+  struct EgoEntry *ego_entry = cls;
+  struct GNUNET_GNSRECORD_Data token_record[2];
+  struct GNUNET_HashCode key_hash;
+  struct GNUNET_TIME_Relative token_rel_exp;
+  struct GNUNET_TIME_Relative token_ttl;
+  struct GNUNET_TIME_Absolute token_exp;
+  struct GNUNET_TIME_Absolute token_nbf;
+  struct GNUNET_TIME_Absolute new_exp;
+  struct GNUNET_TIME_Absolute new_iat;
+  struct GNUNET_TIME_Absolute new_nbf;
+  struct GNUNET_IDENTITY_PROVIDER_Token *new_token;
+  json_t *payload_json;
+  json_t *value;
+  json_t *cur_value;
+  json_t *token_nbf_json;
+  json_t *token_exp_json;
+  size_t token_metadata_len;
+
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
+                                      &pub_key);
+
+  //Note: We need the token expiration time here. Not the record expiration
+  //time.
+  //There are two types of tokens: Token that expire on GNS level with
+  //an absolute expiration time. Those are basically tokens that will
+  //be automatically revoked on (record)expiration.
+  //Tokens stored with relative expiration times will expire on the token level (token expiration)
+  //but this service will reissue new tokens that can be retrieved from GNS
+  //automatically.
+
+  payload_json = token->payload;
+
+  token_exp_json = json_object_get (payload_json, "exp");
+  token_nbf_json = json_object_get (payload_json, "nbf");
+  token_exp.abs_value_us = json_integer_value(token_exp_json);
+  token_nbf.abs_value_us = json_integer_value(token_nbf_json);
+  token_rel_exp = GNUNET_TIME_absolute_get_difference (token_nbf, token_exp);
+
+  token_ttl = GNUNET_TIME_absolute_get_remaining (token_exp);
+  if (0 != GNUNET_TIME_absolute_get_remaining (token_exp).rel_value_us)
+  {
+    //This token is not yet expired! Save and skip
+    if (min_rel_exp.rel_value_us > token_ttl.rel_value_us)
+    {
+      min_rel_exp = token_ttl;
+    }
+    json_decref (payload_json);
+    GNUNET_free (token);
+    token = NULL;
+    GNUNET_free (label);
+    label = NULL;
+    GNUNET_free (scopes);
+    scopes = NULL;
+    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Token is expired. Create a new one\n");
+  new_token = GNUNET_IDENTITY_PROVIDER_token_create (&pub_key,
+                                                     &token->aud_key);
+  new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp);
+  new_nbf = GNUNET_TIME_absolute_get ();
+  new_iat = new_nbf;
+
+  json_object_foreach(payload_json, key, value) {
+    if (0 == strcmp (key, "exp"))
+    {
+      GNUNET_IDENTITY_PROVIDER_token_add_json (new_token, key, json_integer (new_exp.abs_value_us));
+    }
+    else if (0 == strcmp (key, "nbf"))
+    {
+      GNUNET_IDENTITY_PROVIDER_token_add_json (new_token, key, json_integer (new_nbf.abs_value_us));
+    }
+    else if (0 == strcmp (key, "iat"))
+    {
+      GNUNET_IDENTITY_PROVIDER_token_add_json (new_token, key, json_integer (new_iat.abs_value_us));
+    }
+    else if ((0 == strcmp (key, "iss"))
+             || (0 == strcmp (key, "aud")))
+    {
+      //Omit
+    }
+    else if ((0 == strcmp (key, "sub"))
+             || (0 == strcmp (key, "rnl")))
+    {
+      GNUNET_IDENTITY_PROVIDER_token_add_json (new_token, key, value);
+    }
+    else {
+      GNUNET_CRYPTO_hash (key,
+                          strlen (key),
+                          &key_hash);
+      //Check if attr still exists. omit of not
+      if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (ego_entry->attr_map,
+                                                               &key_hash))
+      {
+        cur_value = GNUNET_CONTAINER_multihashmap_get (ego_entry->attr_map,
+                                                       &key_hash);
+        GNUNET_IDENTITY_PROVIDER_token_add_json (new_token, key, cur_value);
+      }
+    }
+  }
+
+  // reassemble and set
+  GNUNET_assert (GNUNET_IDENTITY_PROVIDER_token_serialize (new_token,
+                                                           priv_key,
+                                                           &new_ecdhe_privkey,
+                                                           &enc_token_str));
+
+  json_decref (payload_json);
+
+  token_record[0].data = enc_token_str;
+  token_record[0].data_size = strlen (enc_token_str) + 1;
+  token_record[0].expiration_time = rd_exp; //Old expiration time
+  token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN;
+  token_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
+
+  //Meta
+  token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
+    + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
+    + strlen (scopes) + 1; //With 0-Terminator
+  token_metadata = GNUNET_malloc (token_metadata_len);
+  write_ptr = token_metadata;
+  memcpy (token_metadata, new_ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
+  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
+  memcpy (write_ptr, &token->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
+  memcpy (write_ptr, scopes, strlen (scopes) + 1); //with 0-Terminator;
+
+  token_record[1].data = token_metadata;
+  token_record[1].data_size = token_metadata_len;
+  token_record[1].expiration_time = rd_exp;
+  token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
+  token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
+
+  ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                          priv_key,
+                                          label,
+                                          2,
+                                          token_record,
+                                          &store_token_cont,
+                                          ego_entry);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, ">>> Updating Token w/ %s\n", new_token);
+  GNUNET_IDENTITY_PROVIDER_token_destroy (new_token);
+  GNUNET_IDENTITY_PROVIDER_token_destroy (token);
+  GNUNET_free (new_ecdhe_privkey);
+  GNUNET_free (enc_token_str);
+  token = NULL;
+  GNUNET_free (label);
+  label = NULL;
+  GNUNET_free (scopes);
+  scopes = NULL;
+}
+
+static void
+update_identities(void *cls,
+                  const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+/**
+ *
+ * Cleanup attr_map
+ *
+ * @param cls NULL
+ * @param key the key
+ * @param value the json_t attribute value
+ * @return GNUNET_YES
+ */
+static int
+clear_ego_attrs (void *cls,
+                 const struct GNUNET_HashCode *key,
+                 void *value)
+{
+  json_t *attr_value = value;
+
+  json_decref (attr_value);
+
+  return GNUNET_YES;
+}
+
+
+/**
+ *
+ * Update all ID_TOKEN records for an identity and store them
+ *
+ * @param cls the identity entry
+ * @param zone the identity
+ * @param lbl the name of the record
+ * @param rd_count number of records
+ * @param rd record data
+ *
+ */
+static void
+token_collect (void *cls,
+               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+               const char *lbl,
+               unsigned int rd_count,
+               const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct EgoEntry *ego_entry = cls;
+  const struct GNUNET_GNSRECORD_Data *token_record;
+  const struct GNUNET_GNSRECORD_Data *token_metadata_record;
+  struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
+
+  if (NULL == lbl)
+  {
+    //Done
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                ">>> Updating Ego finished\n");
+    //Clear attribute map for ego
+    GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map,
+                                           &clear_ego_attrs,
+                                           ego_entry);
+    GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map);
+    GNUNET_SCHEDULER_add_now (&update_identities, ego_entry->next);
+    return;
+  }
+
+  //There should be only a single record for a token under a label
+  if (2 != rd_count)
+  {
+    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
+    return;
+  }
+
+  if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
+  {
+    token_metadata_record = &rd[0];
+    token_record = &rd[1];
+  } else {
+    token_record = &rd[0];
+    token_metadata_record = &rd[1];
+  }
+  GNUNET_assert (token_metadata_record->record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA);
+  GNUNET_assert (token_record->record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN);
+
+  //Get metadata and decrypt token
+  ecdhe_privkey = *((struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data);
+  aud_key = (struct GNUNET_CRYPTO_EcdsaPublicKey *)&ecdhe_privkey+sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey);
+  scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+
+  GNUNET_IDENTITY_PROVIDER_token_parse2 (token_record->data,
+                                         &ecdhe_privkey,
+                                         aud_key,
+                                         &token);
+
+  //token = GNUNET_GNSRECORD_value_to_string (rd->record_type,
+  //                                          rd->data,
+  //                                          rd->data_size);
+  label = GNUNET_strdup (lbl); 
+  rd_exp = token_record->expiration_time;
+
+  GNUNET_SCHEDULER_add_now (&handle_token_update, ego_entry);
+}
+
+
+/**
+ *
+ * Collect all ID_ATTR records for an identity and store them
+ *
+ * @param cls the identity entry
+ * @param zone the identity
+ * @param lbl the name of the record
+ * @param rd_count number of records
+ * @param rd record data
+ *
+ */
+static void
+attribute_collect (void *cls,
+                   const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                   const char *lbl,
+                   unsigned int rd_count,
+                   const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct EgoEntry *ego_entry = cls;
+  json_t *attr_value;
+  struct GNUNET_HashCode key;
+  char* attr;
+  int i;
+
+  if (NULL == lbl)
+  {
+    //Done
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                ">>> Updating Attributes finished\n");
+    ego_entry->attributes_dirty = GNUNET_NO;
+    GNUNET_SCHEDULER_add_now (&update_identities, ego_entry);
+    return;
+  }
+
+  if (0 == rd_count)
+  {
+    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
+    return;
+  }
+  GNUNET_CRYPTO_hash (lbl,
+                      strlen (lbl),
+                      &key);
+  if (1 == rd_count)
+  {
+    if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
+    {
+      attr = GNUNET_GNSRECORD_value_to_string (rd->record_type,
+                                               rd->data,
+                                               rd->data_size);
+      attr_value = json_string (attr);
+      GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
+                                         &key,
+                                         attr_value,
+                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+      GNUNET_free (attr);
+    }
+
+    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
+    return;
+  }
+
+  attr_value = json_array();
+  for (i = 0; i < rd_count; i++)
+  {
+    if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
+    {
+      attr = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
+                                               rd[i].data,
+                                               rd[i].data_size);
+      json_array_append_new (attr_value, json_string (attr));
+      GNUNET_free (attr);
+    }
+
+  }
+  GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
+                                     &key,
+                                     attr_value,
+                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+  GNUNET_NAMESTORE_zone_iterator_next (ns_it);
+  return;
+}
+
+/**
+ *
+ * Update identity information for ego. If attribute map is
+ * dirty, first update the attributes.
+ *
+ * @param cls the ego to update
+ * param tc task context
+ *
+ */
+static void
+update_identities(void *cls,
+                  const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct EgoEntry *next_ego = cls;
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+  if (NULL == next_ego)
+  {
+    if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us)
+      min_rel_exp = MIN_WAIT_TIME;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                ">>> Finished. Rescheduling in %d\n",
+                min_rel_exp.rel_value_us);
+    ns_it = NULL;
+    //finished -> TODO reschedule
+    update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp,
+                                                &update_identities,
+                                                ego_head);
+    min_rel_exp.rel_value_us = 0;
+    return;
+  }
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego);
+  if (GNUNET_YES == next_ego->attributes_dirty)
+  {
+    //Starting over. We must update the Attributes for they might have changed.
+    ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
+                                                   priv_key,
+                                                   &attribute_collect,
+                                                   next_ego);
+
+  }
+  else
+  {
+    //Ego will be dirty next time
+    next_ego->attributes_dirty = GNUNET_YES;
+    ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
+                                                   priv_key,
+                                                   &token_collect,
+                                                   next_ego);
+  }
+}
+
+
+
+/**
+ * Function called initially to start update task
+ */
+static void
+init_cont ()
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, ">>> Starting Service\n");
+  //Initially iterate all itenties and refresh all tokens
+  update_task = GNUNET_SCHEDULER_add_now (&update_identities, ego_head);
+}
+
+/**
+ * Initial ego collection function.
+ *
+ * @param cls NULL
+ * @param ego ego
+ * @param ctx context
+ * @param identifier ego name
+ */
+static void
+list_ego (void *cls,
+          struct GNUNET_IDENTITY_Ego *ego,
+          void **ctx,
+          const char *identifier)
+{
+  struct EgoEntry *new_entry;
+  if ((NULL == ego) && (STATE_INIT == state))
+  {
+    state = STATE_POST_INIT;
+    init_cont ();
+    return;
+  }
+  if (STATE_INIT == state) {
+    new_entry = GNUNET_malloc (sizeof (struct EgoEntry));
+    new_entry->ego = ego;
+    new_entry->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
+                                                                GNUNET_NO);
+    new_entry->attributes_dirty = GNUNET_YES;
+    GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry);
+  }
+}
+
+/**
+ * Cleanup task
+ */
+static void
+cleanup()
+{
+  struct EgoEntry *ego_entry;
+  struct EgoEntry *ego_tmp;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up\n");
+  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 != 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);
+  if (NULL != token)
+    GNUNET_free (token);
+  if (NULL != label)
+    GNUNET_free (label);
+
+  for (ego_entry = ego_head;
+       NULL != ego_entry;)
+  {
+    ego_tmp = ego_entry;
+    if (0 != GNUNET_CONTAINER_multihashmap_size (ego_tmp->attr_map))
+    {
+      GNUNET_CONTAINER_multihashmap_iterate (ego_tmp->attr_map,
+                                             &clear_ego_attrs,
+                                             ego_tmp);
+
+    }
+    GNUNET_CONTAINER_multihashmap_destroy (ego_tmp->attr_map);
+    ego_entry = ego_entry->next;
+    GNUNET_free (ego_tmp);
+  }
+}
+
+/**
+ * Shutdown task
+ *
+ * @param cls NULL
+ * @param tc task context
+ */
+static void
+do_shutdown (void *cls,
+             const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Shutting down...\n");
+  cleanup();
+}
+
+/**
+ * Main function that will be run
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL)
+ * @param c configuration
+ */
+static void
+run (void *cls, 
+     char *const *args, 
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  cfg = c;
+
+
+  //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");
+  }
+
+  identity_handle = GNUNET_IDENTITY_connect (cfg,
+                                             &list_ego,
+                                             NULL);
+
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                &do_shutdown, NULL);
+}
+
+
+/**
+ *
+ * The main function for gnunet-service-identity-token
+ *
+ * @param argc number of arguments from the cli
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ *
+ */
+int
+main (int argc, char *const *argv)
+{
+  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  int ret;
+
+  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+    return 2;
+  GNUNET_log_setup ("gnunet-service-identity-token", "WARNING", NULL);
+  ret =
+    (GNUNET_OK ==
+     GNUNET_PROGRAM_run (argc, argv, "gnunet-service-identity-token",
+                         _("GNUnet identity token service"),
+                         options,
+                         &run, NULL)) ? 0: 1;
+  GNUNET_free_non_null ((char *) argv);
+  return ret;
+}
+
+/* end of gnunet-rest-server.c */
diff --git a/src/identity-provider/identity-token.c b/src/identity-provider/identity-token.c
new file mode 100644 (file)
index 0000000..a9f210b
--- /dev/null
@@ -0,0 +1,827 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2010-2015 Christian Grothoff (and other contributing authors)
+
+      GNUnet is free software; you can redistribute it and/or modify
+      it under the terms of the GNU General Public License as published
+      by the Free Software Foundation; either version 3, or (at your
+      option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      General Public License for more details.
+
+      You should have received a copy of the GNU General Public License
+      along with GNUnet; see the file COPYING.  If not, write to the
+      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+      Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file identity-token/identity-token.c
+ * @brief helper library to manage identity tokens
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_signatures.h"
+#include "gnunet_identity_provider_lib.h"
+#include <jansson.h>
+
+
+/**
+ * Crypto helper functions
+ */
+
+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_ERROR, "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;
+}
+
+
+
+/**
+ * Decrypts metainfo part from a token code
+ */
+static int
+decrypt_str_ecdhe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                   const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key,
+                   const char *cyphertext,
+                   size_t cyphertext_len,
+                   char **result_str)
+{
+  struct GNUNET_HashCode new_key_hash;
+  struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
+  struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
+
+  char *str_buf = GNUNET_malloc (cyphertext_len);
+  size_t str_size;
+
+  //Calculate symmetric key from ecdh parameters
+  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_ecdh (priv_key,
+                                                        ecdh_key,
+                                                        &new_key_hash));
+
+  create_sym_key_from_ecdh (&new_key_hash,
+                            &enc_key,
+                            &enc_iv);
+
+  str_size = GNUNET_CRYPTO_symmetric_decrypt (cyphertext,
+                                              cyphertext_len,
+                                              &enc_key,
+                                              &enc_iv,
+                                              str_buf);
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Decrypted bytes: %d Expected bytes: %d\n", str_size, cyphertext_len);
+  if (-1 == str_size)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH invalid\n");
+    GNUNET_free (str_buf);
+    return GNUNET_SYSERR;
+  }
+  *result_str = GNUNET_malloc (str_size+1);
+  memcpy (*result_str, str_buf, str_size);
+  (*result_str)[str_size] = '\0';
+  GNUNET_free (str_buf);
+  return GNUNET_OK;
+
+}
+
+/**
+ * Decrypt string using pubkey and ECDHE
+*/
+static int
+decrypt_str_ecdhe2 (const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_privkey,
+                    const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                    const char *ciphertext,
+                    size_t ciphertext_len,
+                    char **plaintext)
+{
+  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
+  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+  struct GNUNET_HashCode new_key_hash;
+
+  //This is true see documentation for GNUNET_CRYPTO_symmetric_encrypt
+  *plaintext = GNUNET_malloc (ciphertext_len);
+
+  // Derived key K = H(eB)
+  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (ecdh_privkey,
+                                                        aud_key,
+                                                        &new_key_hash));
+  create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
+  GNUNET_CRYPTO_symmetric_decrypt (ciphertext,
+                                   ciphertext_len,
+                                   &skey, &iv,
+                                   *plaintext);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Encrypt string using pubkey and ECDHE
+ * Returns ECDHE pubkey to be used for decryption
+ */
+static int
+encrypt_str_ecdhe (const char *plaintext,
+                   const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key,
+                   char **cyphertext,
+                   struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
+                   struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pubkey)
+{
+  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
+  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+  struct GNUNET_HashCode new_key_hash;
+  ssize_t enc_size;
+
+  // ECDH keypair E = eG
+  *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
+  GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
+                                      ecdh_pubkey);
+
+  //This is true see documentation for GNUNET_CRYPTO_symmetric_encrypt
+  *cyphertext = GNUNET_malloc (strlen (plaintext));
+
+  // Derived key K = H(eB)
+  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
+                                                        pub_key,
+                                                        &new_key_hash));
+  create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Encrypting string %s\n (len=%d)",
+              plaintext,
+              strlen (plaintext));
+  enc_size = GNUNET_CRYPTO_symmetric_encrypt (plaintext, strlen (plaintext),
+                                              &skey, &iv,
+                                              *cyphertext);
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Encrypted (len=%d)", enc_size);
+  return GNUNET_OK;
+}
+
+
+
+
+/**
+ * Identity Token API
+ */
+
+
+/**
+ * Create an Identity Token
+ *
+ * @param type the JSON API resource type
+ * @param id the JSON API resource id
+ * @return a new JSON API resource or NULL on error.
+ */
+struct GNUNET_IDENTITY_PROVIDER_Token*
+GNUNET_IDENTITY_PROVIDER_token_create (const struct GNUNET_CRYPTO_EcdsaPublicKey* iss,
+                                       const struct GNUNET_CRYPTO_EcdsaPublicKey* aud)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Token *token;
+  char* audience;
+  char* issuer;
+
+  issuer = GNUNET_STRINGS_data_to_string_alloc (iss,
+                                                sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  audience = GNUNET_STRINGS_data_to_string_alloc (aud,
+                                                  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+
+
+
+  token = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Token));
+
+  token->header = json_object();
+  token->payload = json_object();
+
+  json_object_set_new (token->header, "alg", json_string ("ED512"));
+  json_object_set_new (token->header, "typ", json_string ("JWT"));
+
+  json_object_set_new (token->payload, "iss", json_string (issuer));
+  json_object_set_new (token->payload, "aud", json_string (audience));
+
+  token->aud_key = *aud;
+  GNUNET_free (issuer);
+  GNUNET_free (audience);
+  return token;
+}
+
+void
+GNUNET_IDENTITY_PROVIDER_token_destroy (struct GNUNET_IDENTITY_PROVIDER_Token *token)
+{
+  json_decref (token->header);
+  json_decref (token->payload);
+  GNUNET_free (token);
+}
+
+void
+GNUNET_IDENTITY_PROVIDER_token_add_attr (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
+                                         const char* key,
+                                         const char* value)
+{
+  GNUNET_assert (NULL != token);
+  GNUNET_assert (NULL != token->payload);
+
+  json_object_set_new (token->payload, key, json_string (value));
+}
+
+void
+GNUNET_IDENTITY_PROVIDER_token_add_json (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
+                                         const char* key,
+                                         json_t* value)
+{
+  GNUNET_assert (NULL != token);
+  GNUNET_assert (NULL != token->payload);
+
+  json_object_set_new (token->payload, key, value);
+}
+
+
+int
+GNUNET_IDENTITY_PROVIDER_token_parse2 (const char* raw_data,
+                                       const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
+                                       const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                                       struct GNUNET_IDENTITY_PROVIDER_Token **result)
+{
+  char *enc_token_str;
+  char *tmp_buf;
+  char *token_str;
+  char *enc_token;
+  char *header;
+  char *header_base64;
+  char *payload;
+  char *payload_base64;
+  size_t enc_token_len;
+  json_error_t err_json;
+
+  GNUNET_asprintf (&tmp_buf, "%s", raw_data);
+  strtok (tmp_buf, ",");
+  enc_token_str = strtok (NULL, ",");
+
+  enc_token_len = GNUNET_STRINGS_base64_decode (enc_token_str,
+                                                strlen (enc_token_str),
+                                                &enc_token);
+  if (GNUNET_OK != decrypt_str_ecdhe2 (priv_key,
+                                       aud_key,
+                                       enc_token,
+                                       enc_token_len,
+                                       &token_str))
+  {
+    GNUNET_free (tmp_buf);
+    GNUNET_free (enc_token);
+    return GNUNET_SYSERR;
+  }
+
+  header_base64 = strtok (token_str, ".");
+  payload_base64 = strtok (NULL, ".");
+
+  GNUNET_STRINGS_base64_decode (header_base64,
+                                strlen (header_base64),
+                                &header);
+  GNUNET_STRINGS_base64_decode (payload_base64,
+                                strlen (payload_base64),
+                                &payload);
+  //TODO signature
+
+
+  *result = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Token));
+  (*result)->aud_key =  *aud_key;
+  (*result)->header = json_loads (header, JSON_DECODE_ANY, &err_json);
+  (*result)->payload = json_loads (payload, JSON_DECODE_ANY, &err_json);
+  GNUNET_free (enc_token);
+  GNUNET_free (token_str);
+  GNUNET_free (tmp_buf);
+  GNUNET_free (payload);
+  GNUNET_free (header);
+  return GNUNET_OK;
+}
+
+int
+GNUNET_IDENTITY_PROVIDER_token_parse (const char* raw_data,
+                                      const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                                      struct GNUNET_IDENTITY_PROVIDER_Token **result)
+{
+  char *ecdh_pubkey_str;
+  char *enc_token_str;
+  char *tmp_buf;
+  char *token_str;
+  char *enc_token;
+  char *header;
+  char *header_base64;
+  char *payload;
+  char *payload_base64;
+  size_t enc_token_len;
+  json_error_t err_json;
+  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
+
+  GNUNET_asprintf (&tmp_buf, "%s", raw_data);
+  ecdh_pubkey_str = strtok (tmp_buf, ",");
+  enc_token_str = strtok (NULL, ",");
+
+  GNUNET_STRINGS_string_to_data (ecdh_pubkey_str,
+                                 strlen (ecdh_pubkey_str),
+                                 &ecdh_pubkey,
+                                 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+  enc_token_len = GNUNET_STRINGS_base64_decode (enc_token_str,
+                                                strlen (enc_token_str),
+                                                &enc_token);
+  if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
+                                      &ecdh_pubkey,
+                                      enc_token,
+                                      enc_token_len,
+                                      &token_str))
+  {
+    GNUNET_free (tmp_buf);
+    GNUNET_free (enc_token);
+    return GNUNET_SYSERR;
+  }
+
+  header_base64 = strtok (token_str, ".");
+  payload_base64 = strtok (NULL, ".");
+
+  GNUNET_STRINGS_base64_decode (header_base64,
+                                strlen (header_base64),
+                                &header);
+  GNUNET_STRINGS_base64_decode (payload_base64,
+                                strlen (payload_base64),
+                                &payload);
+  //TODO signature and aud key
+
+
+  *result = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Token));
+  (*result)->header = json_loads (header, JSON_DECODE_ANY, &err_json);
+  (*result)->payload = json_loads (payload, JSON_DECODE_ANY, &err_json);
+  GNUNET_free (enc_token);
+  GNUNET_free (token_str);
+  GNUNET_free (tmp_buf);
+  GNUNET_free (payload);
+  GNUNET_free (header);
+  return GNUNET_OK;
+}
+
+int
+GNUNET_IDENTITY_PROVIDER_token_to_string (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
+                                          const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                                          char **result)
+{
+  char *payload_str;
+  char *header_str;
+  char *payload_base64;
+  char *header_base64;
+  char *padding;
+  char *signature_target;
+  char *signature_str;
+  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
+  header_str = json_dumps (token->header, JSON_COMPACT);
+  GNUNET_STRINGS_base64_encode (header_str,
+                                strlen (header_str),
+                                &header_base64);
+  //Remove GNUNET padding of base64
+  padding = strtok(header_base64, "=");
+  while (NULL != padding)
+    padding = strtok(NULL, "=");
+
+  payload_str = json_dumps (token->payload, JSON_COMPACT);
+  GNUNET_STRINGS_base64_encode (payload_str,
+                                strlen (payload_str),
+                                &payload_base64);
+
+  //Remove GNUNET padding of base64
+  padding = strtok(payload_base64, "=");
+  while (NULL != padding)
+    padding = strtok(NULL, "=");
+
+  GNUNET_asprintf (&signature_target, "%s,%s", header_base64, payload_base64);
+  purpose =
+    GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
+                   strlen (signature_target));
+  purpose->size =
+    htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
+  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
+  memcpy (&purpose[1], signature_target, strlen (signature_target));
+  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
+                                             purpose,
+                                             (struct GNUNET_CRYPTO_EcdsaSignature *)&token->signature))
+  {
+    GNUNET_free (signature_target);
+    GNUNET_free (payload_str);
+    GNUNET_free (header_str);
+    GNUNET_free (payload_base64);
+    GNUNET_free (header_base64);
+    GNUNET_free (purpose);
+    return GNUNET_SYSERR;
+  }
+
+  GNUNET_STRINGS_base64_encode ((const char*)&token->signature,
+                                sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
+                                &signature_str);
+  GNUNET_asprintf (result, "%s.%s.%s",
+                   header_base64, payload_base64, signature_str);
+  GNUNET_free (signature_target);
+  GNUNET_free (payload_str);
+  GNUNET_free (header_str);
+  GNUNET_free (signature_str);
+  GNUNET_free (payload_base64);
+  GNUNET_free (header_base64);
+  GNUNET_free (purpose);
+  return GNUNET_OK;
+}
+
+int
+GNUNET_IDENTITY_PROVIDER_token_serialize (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
+                                          const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                                          struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
+                                          char **result)
+{
+  char *token_str;
+  char *enc_token;
+  char *dh_key_str;
+  char *enc_token_base64;
+  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
+
+  GNUNET_assert (GNUNET_OK == GNUNET_IDENTITY_PROVIDER_token_to_string (token,
+                                                                        priv_key,
+                                                                        &token_str));
+
+  GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (token_str,
+                                                 &token->aud_key,
+                                                 &enc_token,
+                                                 ecdh_privkey,
+                                                 &ecdh_pubkey));
+  GNUNET_STRINGS_base64_encode (enc_token,
+                                strlen (token_str),
+                                &enc_token_base64);
+  dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ecdh_pubkey,
+                                                    sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+  GNUNET_asprintf (result, "%s,%s", dh_key_str, enc_token_base64);
+  GNUNET_free (dh_key_str);
+  GNUNET_free (enc_token_base64);
+  GNUNET_free (enc_token);
+  GNUNET_free (token_str);
+  return GNUNET_OK;
+}
+
+struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload*
+GNUNET_IDENTITY_PROVIDER_ticket_payload_create (const char* nonce,
+                                                const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
+                                                const char* lbl_str)
+{
+  struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload* payload;
+
+  payload = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload));
+  GNUNET_asprintf (&payload->nonce, nonce, strlen (nonce));
+  payload->identity_key = *identity_pkey;
+  GNUNET_asprintf (&payload->label, lbl_str, strlen (lbl_str));
+  return payload;
+}
+
+void
+GNUNET_IDENTITY_PROVIDER_ticket_payload_destroy (struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload* payload)
+{
+  GNUNET_free (payload->nonce);
+  GNUNET_free (payload->label);
+  GNUNET_free (payload);
+}
+
+void
+GNUNET_IDENTITY_PROVIDER_ticket_payload_serialize (struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload *payload,
+                                                   char **result)
+{
+  char* identity_key_str;
+
+  identity_key_str = GNUNET_STRINGS_data_to_string_alloc (&payload->identity_key,
+                                                          sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+
+  GNUNET_asprintf (result, 
+                   "{\"nonce\": \"%u\",\"identity\": \"%s\",\"label\": \"%s\"}",
+                   payload->nonce, identity_key_str, payload->label);
+  GNUNET_free (identity_key_str);
+
+}
+
+
+/**
+ * Create the token code
+ * The metadata is encrypted with a share ECDH derived secret using B (aud_key)
+ * and e (ecdh_privkey)
+ * The ticket also contains E (ecdh_pubkey) and a signature over the
+ * metadata and E
+ */
+struct GNUNET_IDENTITY_PROVIDER_TokenTicket*
+GNUNET_IDENTITY_PROVIDER_ticket_create (const char* nonce_str,
+                                        const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
+                                        const char* lbl_str,
+                                        const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key)
+{
+  struct GNUNET_IDENTITY_PROVIDER_TokenTicket *ticket;
+  struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload *code_payload;
+
+  ticket = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_TokenTicket));
+  code_payload = GNUNET_IDENTITY_PROVIDER_ticket_payload_create (nonce_str,
+                                                                 identity_pkey,
+                                                                 lbl_str);
+  ticket->aud_key = *aud_key;
+  ticket->payload = code_payload;
+
+
+  return ticket;
+}
+
+void
+GNUNET_IDENTITY_PROVIDER_ticket_destroy (struct GNUNET_IDENTITY_PROVIDER_TokenTicket *ticket)
+{
+  GNUNET_IDENTITY_PROVIDER_ticket_payload_destroy (ticket->payload);
+  GNUNET_free (ticket);
+}
+
+int
+GNUNET_IDENTITY_PROVIDER_ticket_serialize (struct GNUNET_IDENTITY_PROVIDER_TokenTicket *ticket,
+                                           const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                                           char **result)
+{
+  char *code_payload_str;
+  char *enc_ticket_payload;
+  char *ticket_payload_str;
+  char *ticket_sig_str;
+  char *ticket_str;
+  char *dh_key_str;
+  char *write_ptr;
+  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
+
+  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
+
+  GNUNET_IDENTITY_PROVIDER_ticket_payload_serialize (ticket->payload,
+                                                     &code_payload_str);
+
+  GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (code_payload_str,
+                                                 &ticket->aud_key,
+                                                 &enc_ticket_payload,
+                                                 &ecdhe_privkey,
+                                                 &ticket->ecdh_pubkey));
+
+  GNUNET_free (ecdhe_privkey);
+
+  purpose = 
+    GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 
+                   sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
+                   strlen (code_payload_str)); // E_K (code_str)
+  purpose->size = 
+    htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
+           sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
+           strlen (code_payload_str));
+  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
+  write_ptr = (char*) &purpose[1];
+  memcpy (write_ptr,
+          &ticket->ecdh_pubkey,
+          sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
+  memcpy (write_ptr, enc_ticket_payload, strlen (code_payload_str));
+  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign (priv_key,
+                                                        purpose,
+                                                       &ticket->signature));
+  GNUNET_STRINGS_base64_encode (enc_ticket_payload,
+                                strlen (code_payload_str),
+                                &ticket_payload_str);
+  ticket_sig_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->signature,
+                                                        sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+
+  dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->ecdh_pubkey,
+                                                    sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Using ECDH pubkey %s to encrypt\n", dh_key_str);
+  GNUNET_asprintf (&ticket_str, "{\"meta\": \"%s\", \"ecdh\": \"%s\", \"signature\": \"%s\"}",
+                   ticket_payload_str, dh_key_str, ticket_sig_str);
+  GNUNET_STRINGS_base64_encode (ticket_str, strlen (ticket_str), result);
+  GNUNET_free (dh_key_str);
+  GNUNET_free (purpose);
+  GNUNET_free (ticket_str);
+  GNUNET_free (ticket_sig_str);
+  GNUNET_free (code_payload_str);
+  GNUNET_free (enc_ticket_payload);
+  GNUNET_free (ticket_payload_str);
+  return GNUNET_OK;
+}
+
+int
+GNUNET_IDENTITY_PROVIDER_ticket_payload_parse(const char *raw_data,
+                                              ssize_t data_len,
+                                              const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                                              const struct GNUNET_CRYPTO_EcdhePublicKey *ecdhe_pkey,
+                                              struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload **result)
+{
+  const char* label_str;
+  const char* nonce_str;
+  const char* identity_key_str;
+
+  json_t *root;
+  json_t *label_json;
+  json_t *identity_json;
+  json_t *nonce_json;
+  json_error_t err_json;
+  char* meta_str;
+  struct GNUNET_CRYPTO_EcdsaPublicKey id_pkey;
+
+  if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
+                                      ecdhe_pkey,
+                                      raw_data,
+                                      data_len,
+                                      &meta_str))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Metadata decryption failed\n");
+    return GNUNET_SYSERR;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Metadata: %s\n", meta_str);
+  root = json_loads (meta_str, JSON_DECODE_ANY, &err_json);
+  if (!root)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Error parsing metadata: %s\n", err_json.text);
+    GNUNET_free (meta_str);
+    return GNUNET_SYSERR;
+  }
+
+  identity_json = json_object_get (root, "identity");
+  if (!json_is_string (identity_json))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Error parsing metadata: %s\n", err_json.text);
+    json_decref (root);
+    GNUNET_free (meta_str);
+    return GNUNET_SYSERR;
+  }
+  identity_key_str = json_string_value (identity_json);
+  GNUNET_STRINGS_string_to_data (identity_key_str,
+                                 strlen (identity_key_str),
+                                 &id_pkey,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+
+
+  label_json = json_object_get (root, "label");
+  if (!json_is_string (label_json))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Error parsing metadata: %s\n", err_json.text);
+    json_decref (root);
+    GNUNET_free (meta_str);
+    return GNUNET_SYSERR;
+  }
+
+  label_str = json_string_value (label_json);
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Found label: %s\n", label_str);
+
+  nonce_json = json_object_get (root, "nonce");
+  if (!json_is_string (label_json))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Error parsing metadata: %s\n", err_json.text);
+    json_decref (root);
+    GNUNET_free (meta_str);
+    return GNUNET_SYSERR;
+  }
+
+  nonce_str = json_string_value (nonce_json);
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Found nonce: %s\n", nonce_str);
+
+  *result = GNUNET_IDENTITY_PROVIDER_ticket_payload_create (nonce_str,
+                                                            (const struct GNUNET_CRYPTO_EcdsaPublicKey*)&id_pkey,
+                                                            label_str);
+  GNUNET_free (meta_str);
+  json_decref (root);
+  return GNUNET_OK;
+
+}
+
+int
+GNUNET_IDENTITY_PROVIDER_ticket_parse (const char *raw_data,
+                                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                                       struct GNUNET_IDENTITY_PROVIDER_TokenTicket **result)
+{
+  const char* enc_meta_str;
+  const char* ecdh_enc_str;
+  const char* signature_enc_str;
+
+  json_t *root;
+  json_t *signature_json;
+  json_t *ecdh_json;
+  json_t *enc_meta_json;
+  json_error_t err_json;
+  char* enc_meta;
+  char* ticket_decoded;
+  char* write_ptr;
+  size_t enc_meta_len;
+  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
+  struct GNUNET_IDENTITY_PROVIDER_TokenTicket *ticket;
+  struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload *ticket_payload;
+
+  ticket_decoded = NULL;
+  GNUNET_STRINGS_base64_decode (raw_data, strlen (raw_data), &ticket_decoded);
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Token Code: %s\n", ticket_decoded);
+  root = json_loads (ticket_decoded, JSON_DECODE_ANY, &err_json);
+  if (!root)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "%s\n", err_json.text);
+    return GNUNET_SYSERR;
+  }
+
+  signature_json = json_object_get (root, "signature");
+  ecdh_json = json_object_get (root, "ecdh");
+  enc_meta_json = json_object_get (root, "meta");
+
+  signature_enc_str = json_string_value (signature_json);
+  ecdh_enc_str = json_string_value (ecdh_json);
+  enc_meta_str = json_string_value (enc_meta_json);
+
+  ticket = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_TokenTicket));
+
+  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ecdh_enc_str,
+                                                  strlen (ecdh_enc_str),
+                                                  &ticket->ecdh_pubkey,
+                                                  sizeof  (struct GNUNET_CRYPTO_EcdhePublicKey)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH PKEY %s invalid in metadata\n", ecdh_enc_str);
+    json_decref (root);
+    GNUNET_free (ticket);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Using ECDH pubkey %s for metadata decryption\n", ecdh_enc_str);
+  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_enc_str,
+                                                  strlen (signature_enc_str),
+                                                  &ticket->signature,
+                                                  sizeof (struct GNUNET_CRYPTO_EcdsaSignature)))
+  {
+    json_decref (root);
+    GNUNET_free (ticket_decoded);
+    GNUNET_free (ticket);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH signature invalid in metadata\n");
+    return GNUNET_SYSERR;
+  }
+
+  enc_meta_len = GNUNET_STRINGS_base64_decode (enc_meta_str,
+                                               strlen (enc_meta_str),
+                                               &enc_meta);
+
+
+  GNUNET_IDENTITY_PROVIDER_ticket_payload_parse (enc_meta,
+                                                 enc_meta_len,
+                                                 priv_key,
+                                                 (const struct GNUNET_CRYPTO_EcdhePublicKey*)&ticket->ecdh_pubkey,
+                                                 &ticket_payload);
+
+  ticket->payload = ticket_payload;
+  //TODO: check signature here
+  purpose = 
+    GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 
+                   sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
+                   enc_meta_len); // E_K (code_str)
+  purpose->size = 
+    htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
+           sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
+           enc_meta_len);
+  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
+  write_ptr = (char*) &purpose[1];
+  memcpy (write_ptr, &ticket->ecdh_pubkey, sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
+  memcpy (write_ptr, enc_meta, enc_meta_len);
+
+  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET,
+                                               purpose,
+                                               &ticket->signature,
+                                               &ticket_payload->identity_key))
+  {
+    GNUNET_IDENTITY_PROVIDER_ticket_destroy (ticket);
+    GNUNET_free (ticket_decoded);
+    json_decref (root);
+    GNUNET_free (purpose);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Error verifying signature for token code\n");
+    return GNUNET_SYSERR;
+  }
+  *result = ticket;
+  GNUNET_free (purpose);
+
+  GNUNET_free (enc_meta);
+  GNUNET_free (ticket_decoded);
+  json_decref (root);
+  return GNUNET_OK;
+
+}
+
+
+
+/* end of identity-token.c */
diff --git a/src/identity-provider/identity-token.conf b/src/identity-provider/identity-token.conf
new file mode 100644 (file)
index 0000000..f29f6cd
--- /dev/null
@@ -0,0 +1,2 @@
+[identity-token]
+BINARY=gnunet-service-identity-token
diff --git a/src/identity-provider/plugin_rest_identity_token.c b/src/identity-provider/plugin_rest_identity_token.c
new file mode 100644 (file)
index 0000000..d2c1b6c
--- /dev/null
@@ -0,0 +1,1412 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 Christian Grothoff (and other contributing authors)
+
+   GNUnet is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNUnet; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @file 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 "microhttpd.h"
+#include <jansson.h>
+#include "gnunet_signatures.h"
+#include "gnunet_identity_provider_lib.h"
+
+/**
+ * REST root namespace
+ */
+#define GNUNET_REST_API_NS_IDENTITY_TOKEN "/gnuid"
+
+/**
+ * Issue namespace
+ */
+#define GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE "/gnuid/issue"
+
+/**
+ * Check namespace
+ */
+#define GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK "/gnuid/check"
+
+/**
+ * Token namespace
+ */
+#define GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN "/gnuid/token"
+
+/**
+ * Authorize namespace
+ */
+#define GNUNET_REST_API_NS_IDENTITY_OAUTH2_AUTHORIZE "/gnuid/authorize"
+
+#define GNUNET_REST_JSONAPI_IDENTITY_token_ticket "code"
+
+#define GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_GRANT_TYPE_CODE "authorization_code"
+
+#define GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_GRANT_TYPE "grant_type"
+
+#define GNUNET_IDENTITY_TOKEN_REQUEST_NONCE "nonce"
+
+/**
+ * State while collecting all egos
+ */
+#define ID_REST_STATE_INIT 0
+
+/**
+ * Done collecting egos
+ */
+#define ID_REST_STATE_POST_INIT 1
+
+/**
+ * Resource type
+ */
+#define GNUNET_REST_JSONAPI_IDENTITY_TOKEN "token"
+
+/**
+ * URL parameter to create a GNUid token for a specific audience
+ */
+#define GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST "audience"
+
+/**
+ * URL parameter to create a GNUid token for a specific issuer (EGO)
+ */
+#define GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST "issuer"
+
+/**
+ * Attributes passed to issue request
+ */
+#define GNUNET_IDENTITY_TOKEN_ATTR_LIST "requested_attrs"
+
+/**
+ * Token expiration string
+ */
+#define GNUNET_IDENTITY_TOKEN_EXP_STRING "expiration"
+
+/**
+ * Renew token w/ relative expirations
+ */
+#define GNUNET_IDENTITY_TOKEN_RENEW_TOKEN "renew_token"
+
+/**
+ * Error messages
+ */
+#define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid"
+#define GNUNET_REST_ERROR_NO_DATA "No data"
+
+/**
+ * GNUid token lifetime
+ */
+#define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000
+
+/**
+ * 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;
+  
+  /**
+   * Ptr to current ego private key
+   */
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+
+  /**
+   * Handle to the rest connection
+   */
+  struct RestConnectionDataHandle *conndata_handle;
+  
+  /**
+   * The processing state
+   */
+  int state;
+
+  /**
+   * Handle to Identity service.
+   */
+  struct GNUNET_IDENTITY_Handle *identity_handle;
+
+  /**
+   * IDENTITY Operation
+   */
+  struct GNUNET_IDENTITY_Operation *op;
+
+  /**
+   * Handle to NS service
+   */
+  struct GNUNET_NAMESTORE_Handle *ns_handle;
+
+  /**
+   * Handle to GNS service
+   */
+  struct GNUNET_GNS_Handle *gns_handle;
+
+  /**
+   * NS iterator
+   */
+  struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+
+  /**
+   * NS Handle
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+  /**
+   * 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;    
+  
+  /**
+   * GNS lookup
+   */
+  struct GNUNET_GNS_LookupRequest *lookup_request;
+
+  /**
+   * The plugin result processor
+   */
+  GNUNET_REST_ResultProcessor proc;
+
+  /**
+   * The closure of the result processor
+   */
+  void *proc_cls;
+
+  /**
+   * The name to look up
+   */
+  char *name;
+
+  /**
+   * The url
+   */
+  char *url;
+
+  /**
+   * The data from the REST request
+   */
+  const char* data;
+
+  /**
+   * the length of the REST data
+   */
+  size_t data_size;
+
+  /**
+   * HTTP method
+   */
+  const char* method;
+
+  /**
+   * Error response message
+   */
+  char *emsg;
+
+  /**
+   * Identity Token
+   */
+  struct GNUNET_IDENTITY_PROVIDER_Token *token;
+
+  /**
+   * Identity Token Code
+   */
+  struct GNUNET_IDENTITY_PROVIDER_TokenTicket *token_ticket;
+
+  /**
+   * Response object
+   */
+  struct JsonApiObject *resp_object;
+
+  /**
+   * ID Attribute list given
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *attr_map;
+
+
+};
+
+
+/**
+ * Cleanup lookup handle
+ * @param handle Handle to clean up
+ */
+static void
+cleanup_handle (struct RequestHandle *handle)
+{
+  struct EgoEntry *ego_entry;
+  struct EgoEntry *ego_tmp;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up\n");
+  if (NULL != handle->resp_object) 
+    GNUNET_REST_jsonapi_object_delete (handle->resp_object);
+  if (NULL != handle->name)
+    GNUNET_free (handle->name);
+  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->gns_handle)
+    GNUNET_GNS_disconnect (handle->gns_handle);
+  if (NULL != handle->ns_it)
+    GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
+  if (NULL != handle->ns_qe)
+    GNUNET_NAMESTORE_cancel (handle->ns_qe);
+  if (NULL != handle->ns_handle)
+    GNUNET_NAMESTORE_disconnect (handle->ns_handle);
+  if (NULL != handle->attr_map)
+    GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map);
+  if (NULL != handle->token)
+    GNUNET_IDENTITY_PROVIDER_token_destroy (handle->token);
+  if (NULL != handle->token_ticket)
+    GNUNET_IDENTITY_PROVIDER_ticket_destroy (handle->token_ticket);
+  if (NULL != handle->url)
+    GNUNET_free (handle->url);
+  if (NULL != handle->emsg)
+    GNUNET_free (handle->emsg);
+  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);
+  }
+  GNUNET_free (handle);
+}
+
+
+/**
+ * Task run on shutdown.  Cleans up everything.
+ *
+ * @param cls unused
+ * @param tc scheduler context
+ */
+static void
+do_error (void *cls,
+          const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  char *json_error;
+
+  GNUNET_asprintf (&json_error,
+                   "{Error while processing request: %s}",
+                   handle->emsg);
+
+  resp = GNUNET_REST_create_json_response (json_error);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
+  cleanup_handle (handle);
+  GNUNET_free (json_error);
+}
+
+/**
+ * Task run on shutdown.  Cleans up everything.
+ *
+ * @param cls unused
+ * @param tc scheduler context
+ */
+static void
+do_cleanup_handle_delayed (void *cls,
+          const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct RequestHandle *handle = cls;
+  cleanup_handle(handle);
+}
+
+void
+store_token_cont (void *cls,
+                  int32_t success,
+                  const char *emsg)
+{
+  char *result_str;
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+  
+  handle->ns_qe = NULL;
+  if (GNUNET_SYSERR == success)
+  {
+    handle->emsg = GNUNET_strdup (emsg);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  GNUNET_REST_jsonapi_data_serialize (handle->resp_object, &result_str);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
+  resp = GNUNET_REST_create_json_response (result_str);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_free (result_str);
+  GNUNET_SCHEDULER_add_now (&do_cleanup_handle_delayed, handle);
+}
+
+
+
+
+
+
+
+
+
+/**
+ * Build a GNUid token for identity
+ * @param handle the handle
+ * @param ego_entry the ego to build the token for
+ * @param name name of the ego
+ * @param token_aud token audience
+ * @param token the resulting gnuid token
+ * @return identifier string of token (label)
+ */
+static void
+sign_and_return_token (void *cls,
+                       const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
+  struct GNUNET_CRYPTO_EcdsaPublicKey aud_pkey;
+  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
+  struct JsonApiResource *json_resource;
+  struct RequestHandle *handle = cls;
+  struct GNUNET_GNSRECORD_Data token_record[2];
+  struct GNUNET_HashCode key;
+  struct GNUNET_TIME_Relative etime_rel;
+  json_t *token_str;
+  json_t *name_str;
+  json_t *token_ticket_json;
+  char *lbl_str;
+  char *exp_str;
+  char *token_ticket_str;
+  char *audience;
+  char *nonce_str;
+  char *enc_token_str;
+  char *token_metadata;
+  char *scopes;
+  char* write_ptr;
+  uint64_t time;
+  uint64_t exp_time;
+  uint64_t rnd_key;
+  size_t token_metadata_len;
+
+  //Remote nonce 
+  nonce_str = NULL;
+  GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE,
+                      strlen (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE),
+                      &key);
+  if ( GNUNET_YES !=
+       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+                                               &key) )
+  {
+    handle->emsg = GNUNET_strdup ("Request nonce missing!\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+                                                 &key);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str);
+  //Token audience
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST,
+                      strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST),
+                      &key);
+  audience = NULL;
+  if ( GNUNET_YES !=
+       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+                                               &key) )
+  {
+    handle->emsg = GNUNET_strdup ("Audience missing!\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+                                                &key);
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Audience to issue token for: %s\n", audience);
+
+  //Audience pubkey (B = bG)
+  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (audience,
+                                                               strlen (audience),
+                                                               &aud_pkey))
+  {
+    handle->emsg = GNUNET_strdup ("Client PKEY invalid!\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+
+  rnd_key = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
+  GNUNET_STRINGS_base64_encode ((char*)&rnd_key, sizeof (uint64_t), &lbl_str);
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego);
+  GNUNET_CRYPTO_ecdsa_key_get_public (priv_key,
+                                      &pub_key);
+
+  handle->token_ticket = GNUNET_IDENTITY_PROVIDER_ticket_create (nonce_str,
+                                                   &pub_key,
+                                                   lbl_str,
+                                                   &aud_pkey);
+
+  if (GNUNET_OK != GNUNET_IDENTITY_PROVIDER_ticket_serialize (handle->token_ticket,
+                                                  priv_key,
+                                                  &token_ticket_str))
+  {
+    handle->emsg = GNUNET_strdup ("Unable to create ref token!\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING,
+                      strlen (GNUNET_IDENTITY_TOKEN_EXP_STRING),
+                      &key);
+  //Get expiration for token from URL parameter
+  exp_str = NULL;
+  if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+                                                            &key))
+  {
+    exp_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+                                                 &key);
+  }
+  if (NULL == exp_str) {
+    handle->emsg = GNUNET_strdup ("No expiration given!\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_fancy_time_to_relative (exp_str,
+                                             &etime_rel))
+  {
+    handle->emsg = GNUNET_strdup ("Expiration invalid!\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  time = GNUNET_TIME_absolute_get().abs_value_us;
+  exp_time = time + etime_rel.rel_value_us;
+
+  //json_object_set_new (handle->payload, "lbl", json_string (lbl_str));
+  GNUNET_IDENTITY_PROVIDER_token_add_attr (handle->token, "sub", handle->ego_entry->identifier);
+  GNUNET_IDENTITY_PROVIDER_token_add_json (handle->token, "nbf", json_integer (time));
+  GNUNET_IDENTITY_PROVIDER_token_add_json (handle->token, "iat", json_integer (time));
+  GNUNET_IDENTITY_PROVIDER_token_add_json (handle->token, "exp", json_integer (exp_time));
+  GNUNET_IDENTITY_PROVIDER_token_add_attr (handle->token, "nonce", nonce_str);
+
+  
+  handle->resp_object = GNUNET_REST_jsonapi_object_new ();
+
+  json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
+                                                    lbl_str);
+  name_str = json_string (handle->ego_entry->identifier);
+  GNUNET_REST_jsonapi_resource_add_attr (json_resource,
+                                         GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
+                                         name_str);
+  json_decref (name_str);
+  token_str = json_string (enc_token_str);
+  GNUNET_REST_jsonapi_resource_add_attr (json_resource,                                         
+                                         GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
+                                         token_str);
+  token_ticket_json = json_string (token_ticket_str);
+  GNUNET_REST_jsonapi_resource_add_attr (json_resource,
+                                         GNUNET_REST_JSONAPI_IDENTITY_token_ticket,
+                                         token_ticket_json);
+  GNUNET_free (token_ticket_str);
+  json_decref (token_ticket_json);
+  GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource);
+  //Token in a serialized encrypted format 
+  GNUNET_assert (GNUNET_IDENTITY_PROVIDER_token_serialize (handle->token,
+                                                           priv_key,
+                                                           &ecdhe_privkey,
+                                                           &enc_token_str));
+
+  //Token record E,E_K (Token)
+  token_record[0].data = enc_token_str;
+  token_record[0].data_size = strlen (enc_token_str) + 1;
+  token_record[0].expiration_time = exp_time;
+  token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN;
+  token_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
+
+
+  //Meta info
+  GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_ATTR_LIST,
+                      strlen (GNUNET_IDENTITY_TOKEN_ATTR_LIST),
+                      &key);
+
+  scopes = NULL;
+  if ( GNUNET_YES !=
+       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+                                               &key) )
+  {
+    handle->emsg = GNUNET_strdup ("Scopes missing!\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  scopes = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+                                              &key);
+
+  token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
+    + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
+    + strlen (scopes) + 1; //With 0-Terminator
+  token_metadata = GNUNET_malloc (token_metadata_len);
+  write_ptr = token_metadata;
+  memcpy (token_metadata, ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
+  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
+  memcpy (write_ptr, &aud_pkey, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
+  memcpy (write_ptr, scopes, strlen (scopes) + 1); //with 0-Terminator;
+
+  GNUNET_free (ecdhe_privkey);
+
+  token_record[1].data = token_metadata;
+  token_record[1].data_size = token_metadata_len;
+  token_record[1].expiration_time = exp_time;
+  token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
+  token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
+
+  //Persist token
+  handle->ns_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
+                                                  priv_key,
+                                                  lbl_str,
+                                                  2,
+                                                  token_record,
+                                                  &store_token_cont,
+                                                  handle);
+  GNUNET_free (lbl_str);
+  GNUNET_free (enc_token_str);
+  json_decref (token_str);
+}
+
+
+
+
+
+static void
+attr_collect (void *cls,
+              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+              const char *label,
+              unsigned int rd_count,
+              const struct GNUNET_GNSRECORD_Data *rd)
+{
+  int i;
+  char* data;
+  json_t *attr_arr;
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode key;
+
+  if (NULL == label)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n");
+    handle->ns_it = NULL;
+    GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
+    return;
+  }
+
+  GNUNET_CRYPTO_hash (label,
+                      strlen (label),
+                      &key);
+
+  if (0 == rd_count ||
+      ( (NULL != handle->attr_map) &&
+        (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map,
+                                                               &key))
+      )
+     )
+  {
+    GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", label);
+
+  if (1 == rd_count)
+  {
+    if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
+    {
+      data = GNUNET_GNSRECORD_value_to_string (rd->record_type,
+                                               rd->data,
+                                               rd->data_size);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
+      GNUNET_IDENTITY_PROVIDER_token_add_attr (handle->token, label, data);
+      GNUNET_free (data);
+    }
+    GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+    return;
+  }
+
+  i = 0;
+  attr_arr = json_array();
+  for (; i < rd_count; i++)
+  {
+    if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
+    {
+      data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
+                                               rd[i].data,
+                                               rd[i].data_size);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
+      json_array_append_new (attr_arr, json_string (data));
+      GNUNET_free (data);
+    }
+  }
+
+  if (0 < json_array_size (attr_arr))
+  {
+    GNUNET_IDENTITY_PROVIDER_token_add_json (handle->token, label, attr_arr);
+  }
+  json_decref (attr_arr);
+  GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+}
+
+
+/**
+ * Create a response with requested ego(s)
+ *
+ * @param con the Rest handle
+ * @param url the requested url
+ * @param cls the request handle
+ */
+static void
+issue_token_cont (struct RestConnectionDataHandle *con,
+                  const char *url,
+                  void *cls)
+{
+  const char *egoname;
+  char *ego_val;
+  char *audience;
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct GNUNET_HashCode key;
+  struct MHD_Response *resp;
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
+  struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
+
+  if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url,
+                                                GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "URL invalid: %s\n", handle->url);
+    resp = GNUNET_REST_create_json_response (NULL);
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
+    cleanup_handle (handle);
+    return;
+  }
+
+  egoname = NULL;
+  ego_entry = NULL;
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
+                      strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
+                      &key);
+  if ( GNUNET_YES ==
+       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+                                               &key) )
+  {
+    ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+                                                 &key);
+    if (NULL == ego_val)
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Ego invalid: %s\n", ego_val);
+    if (NULL != ego_val)
+    {
+      for (ego_entry = handle->ego_head;
+           NULL != ego_entry;
+           ego_entry = ego_entry->next)
+      {
+        if (0 != strcmp (ego_val, ego_entry->identifier))
+          continue;
+        egoname = ego_entry->identifier;
+        break;
+      }
+      if (NULL == egoname || NULL == ego_entry)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Ego not found: %s\n", ego_val);
+        resp = GNUNET_REST_create_json_response (NULL);
+        handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
+        cleanup_handle (handle);
+        return;
+      }
+    }
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego to issue token for: %s\n", egoname);
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST,
+                      strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST),
+                      &key);
+
+  //Token audience
+  audience = NULL;
+  if ( GNUNET_YES !=
+       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+                                               &key) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Audience missing!\n");
+    resp = GNUNET_REST_create_json_response (NULL);
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
+    cleanup_handle (handle);
+    return;
+  }
+  audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+                                                &key);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Audience to issue token for: %s\n", audience);
+
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
+                                      &pub_key);
+  GNUNET_STRINGS_string_to_data (audience,
+                                 strlen (audience),
+                                 &aud_key,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  handle->token = GNUNET_IDENTITY_PROVIDER_token_create (&pub_key,
+                                                         aud_key);
+  GNUNET_free (aud_key);
+
+
+  //Get identity attributes
+  handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
+  handle->ego_entry = ego_entry;
+  handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
+                                                         priv_key,
+                                                         &attr_collect,
+                                                         handle);
+}
+
+
+/**
+ * Build a GNUid token for identity
+ * @param handle the handle
+ * @param ego_entry the ego to build the token for
+ * @param name name of the ego
+ * @param token_aud token audience
+ * @param token the resulting gnuid token
+ * @return identifier string of token (label)
+ */
+static void
+return_token_list (void *cls,
+                   const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  char* result_str;
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+
+  GNUNET_REST_jsonapi_data_serialize (handle->resp_object, &result_str);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
+  resp = GNUNET_REST_create_json_response (result_str);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_free (result_str);
+  cleanup_handle (handle);
+}
+
+/**
+ * Collect all tokens for ego
+ */
+static void
+token_collect (void *cls,
+               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+               const char *label,
+               unsigned int rd_count,
+               const struct GNUNET_GNSRECORD_Data *rd)
+{
+  int i;
+  char* data;
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_tmp;
+  struct JsonApiResource *json_resource;
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+  json_t *issuer;
+  json_t *token;
+
+  if (NULL == label)
+  {
+    ego_tmp = handle->ego_head;
+    GNUNET_CONTAINER_DLL_remove (handle->ego_head,
+                                 handle->ego_tail,
+                                 ego_tmp);
+    GNUNET_free (ego_tmp->identifier);
+    GNUNET_free (ego_tmp->keystring);
+    GNUNET_free (ego_tmp);
+
+    if (NULL == handle->ego_head)
+    {
+      //Done
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token END\n");
+      handle->ns_it = NULL;
+      GNUNET_SCHEDULER_add_now (&return_token_list, handle);
+      return;
+    }
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Next ego: %s\n", handle->ego_head->identifier);
+    priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
+    handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
+                                                           priv_key,
+                                                           &token_collect,
+                                                           handle);
+    return;
+  }
+
+  for (i = 0; i < rd_count; i++)
+  {
+    if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
+    {
+      data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
+                                               rd[i].data,
+                                               rd[i].data_size);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token: %s\n", data);
+      json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
+                                                        label);
+      issuer = json_string (handle->ego_head->identifier);
+      GNUNET_REST_jsonapi_resource_add_attr (json_resource,
+                                             GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
+                                             issuer);
+      json_decref (issuer);
+      token = json_string (data);
+      GNUNET_REST_jsonapi_resource_add_attr (json_resource,
+                                             GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
+                                             token);
+      json_decref (token);
+
+      GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource);
+      GNUNET_free (data);
+    }
+  }
+
+  GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+}
+
+
+
+/**
+ * Respond to OPTIONS request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+list_token_cont (struct RestConnectionDataHandle *con_handle,
+                 const char* url,
+                 void *cls)
+{
+  char* ego_val;
+  struct GNUNET_HashCode key;
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct EgoEntry *ego_tmp;
+
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
+                      strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
+                      &key);
+
+  if ( GNUNET_YES ==
+       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+                                               &key) )
+  {
+    ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+                                                 &key);
+    //Remove non-matching egos
+    for (ego_entry = handle->ego_head;
+         NULL != ego_entry;)
+    {
+      ego_tmp = ego_entry;
+      ego_entry = ego_entry->next;
+      if (0 != strcmp (ego_val, ego_tmp->identifier))
+      {
+        GNUNET_CONTAINER_DLL_remove (handle->ego_head,
+                                     handle->ego_tail,
+                                     ego_tmp);
+        GNUNET_free (ego_tmp->identifier);
+        GNUNET_free (ego_tmp->keystring);
+        GNUNET_free (ego_tmp);
+      }
+    }
+  }
+  handle->resp_object = GNUNET_REST_jsonapi_object_new ();
+  if (NULL == handle->ego_head)
+  {
+    //Done
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No results.\n");
+    GNUNET_SCHEDULER_add_now (&return_token_list, handle);
+    return;
+  }
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
+  handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
+  handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
+                                                         priv_key,
+                                                         &token_collect,
+                                                         handle);
+
+}
+
+
+
+
+static void
+process_lookup_result (void *cls, uint32_t rd_count,
+                       const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct RequestHandle *handle = cls;
+  json_t *root;
+  struct MHD_Response *resp;
+  char *result;
+  char* token_str;
+  char* record_str;
+
+  handle->lookup_request = NULL;
+  if (2 != rd_count)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Number of tokens %d != 2.",
+                rd_count);
+    handle->emsg = GNUNET_strdup ("Number of tokens != 2.");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  root = json_object();
+  record_str = 
+    GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN,
+                                      rd->data,
+                                      rd->data_size);
+
+  //Decrypt and parse
+  GNUNET_assert (GNUNET_OK ==  GNUNET_IDENTITY_PROVIDER_token_parse (record_str,
+                                                                     handle->priv_key,
+                                                                     &handle->token));
+
+  //Readable
+  GNUNET_assert (GNUNET_OK == GNUNET_IDENTITY_PROVIDER_token_to_string (handle->token,
+                                                                        handle->priv_key,
+                                                                        &token_str));
+
+  json_object_set_new (root, "access_token", json_string (token_str));
+  json_object_set_new (root, "token_type", json_string ("gnuid"));
+  GNUNET_free (token_str);
+  GNUNET_free (record_str);
+
+  result = json_dumps (root, JSON_INDENT(1));
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", result);
+  resp = GNUNET_REST_create_json_response (result);
+  GNUNET_free (result);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  cleanup_handle (handle);
+  json_decref (root);
+}
+
+
+static void
+exchange_token_ticket_cb (void *cls,
+                        struct GNUNET_IDENTITY_Ego *ego,
+                        void **ctx,
+                        const char *name)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode key;
+  char* code;
+  char* lookup_query;
+
+  handle->op = NULL;
+
+  if (NULL == ego)
+  {
+    handle->emsg = GNUNET_strdup ("No GNS identity found.");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_token_ticket,
+                      strlen (GNUNET_REST_JSONAPI_IDENTITY_token_ticket),
+                      &key);
+
+  if ( GNUNET_NO ==
+       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+                                               &key) )
+  {
+    handle->emsg = GNUNET_strdup ("No code given.");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  code = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+                                            &key);
+
+  handle->priv_key = GNUNET_IDENTITY_ego_get_private_key (ego);
+
+  if (GNUNET_SYSERR == GNUNET_IDENTITY_PROVIDER_ticket_parse (code,
+                                                              handle->priv_key,
+                                                              &handle->token_ticket))
+  {
+    handle->emsg = GNUNET_strdup ("Error extracting values from token code.");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Looking for token under %s\n",
+              handle->token_ticket->payload->label);
+  handle->gns_handle = GNUNET_GNS_connect (cfg);
+  GNUNET_asprintf (&lookup_query, "%s.gnu", handle->token_ticket->payload->label);
+  handle->lookup_request = GNUNET_GNS_lookup (handle->gns_handle,
+                                              lookup_query,
+                                              &handle->token_ticket->payload->identity_key,
+                                              GNUNET_GNSRECORD_TYPE_ID_TOKEN,
+                                              GNUNET_GNS_LO_LOCAL_MASTER,
+                                              NULL,
+                                              &process_lookup_result,
+                                              handle);
+  GNUNET_free (lookup_query);
+}
+
+/**
+ * Respond to OAuth2 /token request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+exchange_token_ticket_cont (struct RestConnectionDataHandle *con_handle,
+                          const char* url,
+                          void *cls)
+{
+  struct RequestHandle *handle = cls;
+  char* grant_type;
+  struct GNUNET_HashCode key;
+
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_GRANT_TYPE,
+                      strlen (GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_GRANT_TYPE),
+                      &key);
+
+  if ( GNUNET_YES ==
+       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+                                               &key) )
+  {
+    grant_type = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+                                                    &key);
+  }
+
+  if (0 == strcmp ("authorization_code", grant_type)) {
+    //Get token from GNS
+    handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
+                                      "gns-master",
+                                      &exchange_token_ticket_cb,
+                                      handle);
+  }
+
+  //TODO fail here
+}
+
+/**
+ * Respond to OPTIONS request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+options_cont (struct RestConnectionDataHandle *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_json_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)
+{
+  static const struct GNUNET_REST_RestConnectionHandler handlers[] = {
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE, &issue_token_cont},
+    //{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK, &check_token_cont},
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN, &list_token_cont},
+    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_TOKEN, &options_cont},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN, &exchange_token_ticket_cont},
+    GNUNET_REST_HANDLER_END
+  };
+
+  if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, handlers, handle))
+  {
+    handle->emsg = GNUNET_strdup ("Request unsupported");
+    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;
+    GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
+    GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
+  }
+
+}
+
+/**
+ * Function processing the REST call
+ *
+ * @param method HTTP method
+ * @param url URL of the HTTP request
+ * @param data body of the HTTP request (optional)
+ * @param data_size length of the body
+ * @param proc callback function for the result
+ * @param proc_cls closure for callback function
+ * @return GNUNET_OK if request accepted
+ */
+static void
+rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle,
+                              GNUNET_REST_ResultProcessor proc,
+                              void *proc_cls)
+{
+  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  struct GNUNET_HashCode key;
+  char* attr_list;
+  char* attr_list_tmp;
+  char* attr;
+
+  GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_ATTR_LIST,
+                      strlen (GNUNET_IDENTITY_TOKEN_ATTR_LIST),
+                      &key);
+
+  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+
+  handle->proc_cls = proc_cls;
+  handle->proc = proc;
+  handle->state = ID_REST_STATE_INIT;
+  handle->conndata_handle = conndata_handle;
+  handle->data = conndata_handle->data;
+  handle->data_size = conndata_handle->data_size;
+  handle->method = conndata_handle->method;
+  if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+                                                            &key))
+  {
+    handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
+                                                             GNUNET_NO);
+    attr_list = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+                                                   &key);
+    if (NULL != attr_list)
+    {
+      attr_list_tmp = GNUNET_strdup (attr_list);
+      attr = strtok(attr_list_tmp, ",");
+      for (; NULL != attr; attr = strtok (NULL, ","))
+      {
+        GNUNET_CRYPTO_hash (attr,
+                            strlen (attr),
+                            &key);
+        GNUNET_CONTAINER_multihashmap_put (handle->attr_map,
+                                           &key,
+                                           attr,
+                                           GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+      }
+      GNUNET_free (attr_list_tmp);
+    }
+  }
+
+
+  GNUNET_asprintf (&handle->url, "%s", conndata_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->timeout_task =
+    GNUNET_SCHEDULER_add_delayed (handle->timeout,
+                                  &do_error,
+                                  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_token_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_TOKEN;
+  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_INFO,
+              _("Identity Token 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_token_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 Token REST plugin is finished\n");
+  return NULL;
+}
+
+/* end of plugin_rest_gns.c */
diff --git a/src/identity-token/Makefile.am b/src/identity-token/Makefile.am
deleted file mode 100644 (file)
index a9338ba..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-# This Makefile.am is in the public domain
-AM_CPPFLAGS = -I$(top_srcdir)/src/include
-
- plugindir = $(libdir)/gnunet
-
-if MINGW
- WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols 
-endif
-
-if USE_COVERAGE
-  AM_CFLAGS = --coverage -O0
-  XLIB = -lgcov
-endif
-
-pkgcfgdir= $(pkgdatadir)/config.d/
-
-libexecdir= $(pkglibdir)/libexec/
-
-pkgcfg_DATA = \
-  identity-token.conf
-
-plugin_LTLIBRARIES = \
-       libgnunet_plugin_rest_identity_token.la
-lib_LTLIBRARIES = \
-       libgnunetidentityprovider.la
-
-bin_PROGRAMS = \
- gnunet-identity-token
-
-libexec_PROGRAMS = \
- gnunet-service-identity-token
-
-gnunet_service_identity_token_SOURCES = \
- gnunet-service-identity-token.c
-gnunet_service_identity_token_LDADD = \
- libgnunetidentityprovider.la \
- $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/namestore/libgnunetnamestore.la \
- $(top_builddir)/src/identity/libgnunetidentity.la \
- $(GN_LIBINTL) \
- -ljansson
-
-libgnunetidentityprovider_la_SOURCES = \
-  identity-token.c
-libgnunetidentityprovider_la_LIBADD = \
-       $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
-       $(LTLIBINTL) -ljansson
-
-libgnunet_plugin_rest_identity_token_la_SOURCES = \
-  plugin_rest_identity_token.c
-libgnunet_plugin_rest_identity_token_la_LIBADD = \
-       $(top_builddir)/src/identity/libgnunetidentity.la \
-       $(top_builddir)/src/rest/libgnunetrest.la \
-       $(top_builddir)/src/namestore/libgnunetnamestore.la \
-       $(top_builddir)/src/gns/libgnunetgns.la \
-  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
-  $(LTLIBINTL) -ljansson -lmicrohttpd
-libgnunet_plugin_rest_identity_token_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
-
-gnunet_identity_token_SOURCES = \
- gnunet-identity-token.c         
-gnunet_identity_token_LDADD = \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  -ljansson -lmicrohttpd \
-  $(GN_LIBINTL)
-
-
diff --git a/src/identity-token/gnunet-identity-token.c b/src/identity-token/gnunet-identity-token.c
deleted file mode 100644 (file)
index ad4aae7..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include <jansson.h>
-#include "gnunet_signatures.h"
-
-/**
- * The token
- */
-static char* token;
-
-/**
- * Weather to print the token
- */
-static int print_token;
-
-static void
-run (void *cls,
-     char *const *args,
-     const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  char* payload;
-  char* header;
-  //Get token parts
-  char* header_b64 = strtok (token, ".");
-  char* payload_b64 = strtok(NULL, ".");
-  char* signature_b32 = strtok(NULL, ".");
-  const char* keystring;
-  char* data;
-  json_t *payload_json;
-  json_t *keystring_json;
-  json_error_t error;
-  struct GNUNET_CRYPTO_EcdsaPublicKey key;
-  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-  struct GNUNET_CRYPTO_EcdsaSignature sig;
-  //Decode payload
-  GNUNET_STRINGS_base64_decode (payload_b64,
-                                strlen (payload_b64),
-                                &payload);
-  //Decode header
-  GNUNET_STRINGS_base64_decode (header_b64,
-                                strlen (header_b64),
-                                &header);
-  if (NULL == token)
-    return;
-  
-
-  GNUNET_asprintf(&data,
-                  "%s,%s",
-                  header_b64,
-                  payload_b64);
-  char *val = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + strlen (data));
-  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose*)val;
-  purpose->size = htonl(sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + strlen (data));
-  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
-  memcpy (&purpose[1], data, strlen(data));
-
-  
-  payload_json = json_loads (payload, 0, &error);
-  if ((NULL == payload_json) || !json_is_object (payload_json))
-  {
-    return;
-  }
-  keystring_json =  json_object_get (payload_json, "iss");
-  if (!json_is_string (keystring_json))
-  {
-    return;
-  }
-  keystring = json_string_value (keystring_json);
-  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (keystring,
-                                                               strlen (keystring),
-                                                               &key))
-  {
-    return;
-  }
-  GNUNET_STRINGS_string_to_data (signature_b32,
-                                strlen (signature_b32),
-                                &sig,
-                                sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
-  
-  if (print_token) {
-    printf ("Token:\nHeader:\t\t%s\nPayload:\t%s\nSignature:\t%s\n", header, payload, keystring);
-  }
-  
-  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN,
-                                              purpose,
-                                              &sig,
-                                              &key))
-  {
-    printf("Signature not OK!\n");
-    return;
-  }
-  printf("Signature OK!\n");
-  return;
-}
-int
-main(int argc, char *const argv[])
-{
-  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    {'t', "token", NULL,
-      gettext_noop ("GNUid token"), 1,
-      &GNUNET_GETOPT_set_string, &token},
-    {'p', "print", NULL,
-      gettext_noop ("Print token contents"), 0,
-      &GNUNET_GETOPT_set_one, &print_token},
-
-    GNUNET_GETOPT_OPTION_END
-  };
-  return GNUNET_PROGRAM_run (argc, argv, "ct",
-                             "ct", options,
-                             &run, NULL);
-}
-
-
diff --git a/src/identity-token/gnunet-service-identity-token.c b/src/identity-token/gnunet-service-identity-token.c
deleted file mode 100644 (file)
index 039d1c7..0000000
+++ /dev/null
@@ -1,762 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 Christian Grothoff (and other contributing authors)
-
-   GNUnet is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published
-   by the Free Software Foundation; either version 3, or (at your
-   option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GNUnet; see the file COPYING.  If not, write to the
-   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.
-   */
-/**
- * @author Martin Schanzenbach
- * @file src/rest/gnunet-service-identity-token.c
- * @brief Identity Token Service
- *
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_identity_service.h"
-#include "gnunet_gnsrecord_lib.h"
-#include "gnunet_namestore_service.h"
-#include <jansson.h>
-#include "gnunet_signatures.h"
-#include "gnunet_identity_provider_lib.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
-
-/**
- * Service state (to detect initial update pass)
- */
-static int state;
-
-/**
- * Head of ego entry DLL
- */
-static struct EgoEntry *ego_head;
-
-/**
- * Tail of ego entry DLL
- */
-static struct EgoEntry *ego_tail;
-
-/**
- * Identity handle
- */
-static struct GNUNET_IDENTITY_Handle *identity_handle;
-
-/**
- * Namestore handle
- */
-static struct GNUNET_NAMESTORE_Handle *ns_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;
-
-/**
- * Timeout for next update pass
- */
-static struct GNUNET_TIME_Relative min_rel_exp;
-
-
-/**
- * Currently processed token
- */
-static struct GNUNET_IDENTITY_PROVIDER_Token *token;
-
-/**
- * Label for currently processed token
- */
-static char* label;
-
-/**
- * Scopes for processed token
- */
-static char* scopes;
-
-/**
- * Expiration for processed token
- */
-static uint64_t rd_exp;
-
-/**
- * ECDHE Privkey for processed token metadata
- */
-static struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_privkey;
-
-/**
- * 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;
-
-  /**
-   * Attributes are old and should be updated if GNUNET_YES
-   */
-  int attributes_dirty;
-};
-
-/**
- * Our configuration.
- */
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-
-/**
- * Continuation for token store call
- *
- * @param cls NULL
- * @param success error code
- * @param emsg error message
- */
-static void
-store_token_cont (void *cls,
-                  int32_t success,
-                  const char *emsg)
-{
-  ns_qe = NULL;
-  if (GNUNET_SYSERR == success)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to update token: %s\n",
-                emsg);
-    return;
-  }
-  GNUNET_NAMESTORE_zone_iterator_next (ns_it);
-}
-
-
-/**
- * This function updates the old token with new attributes,
- * removes deleted attributes and expiration times.
- *
- * @param cls the ego entry
- * @param tc task context
- */
-static void
-handle_token_update (void *cls,
-                     const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  char *token_metadata;
-  char *write_ptr;
-  char *enc_token_str;
-  const char *key;
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
-  struct GNUNET_CRYPTO_EcdhePrivateKey *new_ecdhe_privkey;
-  struct EgoEntry *ego_entry = cls;
-  struct GNUNET_GNSRECORD_Data token_record[2];
-  struct GNUNET_HashCode key_hash;
-  struct GNUNET_TIME_Relative token_rel_exp;
-  struct GNUNET_TIME_Relative token_ttl;
-  struct GNUNET_TIME_Absolute token_exp;
-  struct GNUNET_TIME_Absolute token_nbf;
-  struct GNUNET_TIME_Absolute new_exp;
-  struct GNUNET_TIME_Absolute new_iat;
-  struct GNUNET_TIME_Absolute new_nbf;
-  struct GNUNET_IDENTITY_PROVIDER_Token *new_token;
-  json_t *payload_json;
-  json_t *value;
-  json_t *cur_value;
-  json_t *token_nbf_json;
-  json_t *token_exp_json;
-  size_t token_metadata_len;
-
-  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
-                                      &pub_key);
-
-  //Note: We need the token expiration time here. Not the record expiration
-  //time.
-  //There are two types of tokens: Token that expire on GNS level with
-  //an absolute expiration time. Those are basically tokens that will
-  //be automatically revoked on (record)expiration.
-  //Tokens stored with relative expiration times will expire on the token level (token expiration)
-  //but this service will reissue new tokens that can be retrieved from GNS
-  //automatically.
-
-  payload_json = token->payload;
-
-  token_exp_json = json_object_get (payload_json, "exp");
-  token_nbf_json = json_object_get (payload_json, "nbf");
-  token_exp.abs_value_us = json_integer_value(token_exp_json);
-  token_nbf.abs_value_us = json_integer_value(token_nbf_json);
-  token_rel_exp = GNUNET_TIME_absolute_get_difference (token_nbf, token_exp);
-
-  token_ttl = GNUNET_TIME_absolute_get_remaining (token_exp);
-  if (0 != GNUNET_TIME_absolute_get_remaining (token_exp).rel_value_us)
-  {
-    //This token is not yet expired! Save and skip
-    if (min_rel_exp.rel_value_us > token_ttl.rel_value_us)
-    {
-      min_rel_exp = token_ttl;
-    }
-    json_decref (payload_json);
-    GNUNET_free (token);
-    token = NULL;
-    GNUNET_free (label);
-    label = NULL;
-    GNUNET_free (scopes);
-    scopes = NULL;
-    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Token is expired. Create a new one\n");
-  new_token = GNUNET_IDENTITY_PROVIDER_token_create (&pub_key,
-                                                     &token->aud_key);
-  new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp);
-  new_nbf = GNUNET_TIME_absolute_get ();
-  new_iat = new_nbf;
-
-  json_object_foreach(payload_json, key, value) {
-    if (0 == strcmp (key, "exp"))
-    {
-      GNUNET_IDENTITY_PROVIDER_token_add_json (new_token, key, json_integer (new_exp.abs_value_us));
-    }
-    else if (0 == strcmp (key, "nbf"))
-    {
-      GNUNET_IDENTITY_PROVIDER_token_add_json (new_token, key, json_integer (new_nbf.abs_value_us));
-    }
-    else if (0 == strcmp (key, "iat"))
-    {
-      GNUNET_IDENTITY_PROVIDER_token_add_json (new_token, key, json_integer (new_iat.abs_value_us));
-    }
-    else if ((0 == strcmp (key, "iss"))
-             || (0 == strcmp (key, "aud")))
-    {
-      //Omit
-    }
-    else if ((0 == strcmp (key, "sub"))
-             || (0 == strcmp (key, "rnl")))
-    {
-      GNUNET_IDENTITY_PROVIDER_token_add_json (new_token, key, value);
-    }
-    else {
-      GNUNET_CRYPTO_hash (key,
-                          strlen (key),
-                          &key_hash);
-      //Check if attr still exists. omit of not
-      if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (ego_entry->attr_map,
-                                                               &key_hash))
-      {
-        cur_value = GNUNET_CONTAINER_multihashmap_get (ego_entry->attr_map,
-                                                       &key_hash);
-        GNUNET_IDENTITY_PROVIDER_token_add_json (new_token, key, cur_value);
-      }
-    }
-  }
-
-  // reassemble and set
-  GNUNET_assert (GNUNET_IDENTITY_PROVIDER_token_serialize (new_token,
-                                                           priv_key,
-                                                           &new_ecdhe_privkey,
-                                                           &enc_token_str));
-
-  json_decref (payload_json);
-
-  token_record[0].data = enc_token_str;
-  token_record[0].data_size = strlen (enc_token_str) + 1;
-  token_record[0].expiration_time = rd_exp; //Old expiration time
-  token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN;
-  token_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
-
-  //Meta
-  token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
-    + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
-    + strlen (scopes) + 1; //With 0-Terminator
-  token_metadata = GNUNET_malloc (token_metadata_len);
-  write_ptr = token_metadata;
-  memcpy (token_metadata, new_ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
-  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
-  memcpy (write_ptr, &token->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
-  memcpy (write_ptr, scopes, strlen (scopes) + 1); //with 0-Terminator;
-
-  token_record[1].data = token_metadata;
-  token_record[1].data_size = token_metadata_len;
-  token_record[1].expiration_time = rd_exp;
-  token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
-  token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
-
-  ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
-                                          priv_key,
-                                          label,
-                                          2,
-                                          token_record,
-                                          &store_token_cont,
-                                          ego_entry);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, ">>> Updating Token w/ %s\n", new_token);
-  GNUNET_IDENTITY_PROVIDER_token_destroy (new_token);
-  GNUNET_IDENTITY_PROVIDER_token_destroy (token);
-  GNUNET_free (new_ecdhe_privkey);
-  GNUNET_free (enc_token_str);
-  token = NULL;
-  GNUNET_free (label);
-  label = NULL;
-  GNUNET_free (scopes);
-  scopes = NULL;
-}
-
-static void
-update_identities(void *cls,
-                  const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-/**
- *
- * Cleanup attr_map
- *
- * @param cls NULL
- * @param key the key
- * @param value the json_t attribute value
- * @return GNUNET_YES
- */
-static int
-clear_ego_attrs (void *cls,
-                 const struct GNUNET_HashCode *key,
-                 void *value)
-{
-  json_t *attr_value = value;
-
-  json_decref (attr_value);
-
-  return GNUNET_YES;
-}
-
-
-/**
- *
- * Update all ID_TOKEN records for an identity and store them
- *
- * @param cls the identity entry
- * @param zone the identity
- * @param lbl the name of the record
- * @param rd_count number of records
- * @param rd record data
- *
- */
-static void
-token_collect (void *cls,
-               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-               const char *lbl,
-               unsigned int rd_count,
-               const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct EgoEntry *ego_entry = cls;
-  const struct GNUNET_GNSRECORD_Data *token_record;
-  const struct GNUNET_GNSRECORD_Data *token_metadata_record;
-  struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
-
-  if (NULL == lbl)
-  {
-    //Done
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                ">>> Updating Ego finished\n");
-    //Clear attribute map for ego
-    GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map,
-                                           &clear_ego_attrs,
-                                           ego_entry);
-    GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map);
-    GNUNET_SCHEDULER_add_now (&update_identities, ego_entry->next);
-    return;
-  }
-
-  //There should be only a single record for a token under a label
-  if (2 != rd_count)
-  {
-    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
-    return;
-  }
-
-  if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
-  {
-    token_metadata_record = &rd[0];
-    token_record = &rd[1];
-  } else {
-    token_record = &rd[0];
-    token_metadata_record = &rd[1];
-  }
-  GNUNET_assert (token_metadata_record->record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA);
-  GNUNET_assert (token_record->record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN);
-
-  //Get metadata and decrypt token
-  ecdhe_privkey = *((struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data);
-  aud_key = (struct GNUNET_CRYPTO_EcdsaPublicKey *)&ecdhe_privkey+sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey);
-  scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
-  GNUNET_IDENTITY_PROVIDER_token_parse2 (token_record->data,
-                                         &ecdhe_privkey,
-                                         aud_key,
-                                         &token);
-
-  //token = GNUNET_GNSRECORD_value_to_string (rd->record_type,
-  //                                          rd->data,
-  //                                          rd->data_size);
-  label = GNUNET_strdup (lbl); 
-  rd_exp = token_record->expiration_time;
-
-  GNUNET_SCHEDULER_add_now (&handle_token_update, ego_entry);
-}
-
-
-/**
- *
- * Collect all ID_ATTR records for an identity and store them
- *
- * @param cls the identity entry
- * @param zone the identity
- * @param lbl the name of the record
- * @param rd_count number of records
- * @param rd record data
- *
- */
-static void
-attribute_collect (void *cls,
-                   const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                   const char *lbl,
-                   unsigned int rd_count,
-                   const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct EgoEntry *ego_entry = cls;
-  json_t *attr_value;
-  struct GNUNET_HashCode key;
-  char* attr;
-  int i;
-
-  if (NULL == lbl)
-  {
-    //Done
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                ">>> Updating Attributes finished\n");
-    ego_entry->attributes_dirty = GNUNET_NO;
-    GNUNET_SCHEDULER_add_now (&update_identities, ego_entry);
-    return;
-  }
-
-  if (0 == rd_count)
-  {
-    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
-    return;
-  }
-  GNUNET_CRYPTO_hash (lbl,
-                      strlen (lbl),
-                      &key);
-  if (1 == rd_count)
-  {
-    if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
-    {
-      attr = GNUNET_GNSRECORD_value_to_string (rd->record_type,
-                                               rd->data,
-                                               rd->data_size);
-      attr_value = json_string (attr);
-      GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
-                                         &key,
-                                         attr_value,
-                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
-      GNUNET_free (attr);
-    }
-
-    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
-    return;
-  }
-
-  attr_value = json_array();
-  for (i = 0; i < rd_count; i++)
-  {
-    if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
-    {
-      attr = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
-                                               rd[i].data,
-                                               rd[i].data_size);
-      json_array_append_new (attr_value, json_string (attr));
-      GNUNET_free (attr);
-    }
-
-  }
-  GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
-                                     &key,
-                                     attr_value,
-                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
-  GNUNET_NAMESTORE_zone_iterator_next (ns_it);
-  return;
-}
-
-/**
- *
- * Update identity information for ego. If attribute map is
- * dirty, first update the attributes.
- *
- * @param cls the ego to update
- * param tc task context
- *
- */
-static void
-update_identities(void *cls,
-                  const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct EgoEntry *next_ego = cls;
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  if (NULL == next_ego)
-  {
-    if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us)
-      min_rel_exp = MIN_WAIT_TIME;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                ">>> Finished. Rescheduling in %d\n",
-                min_rel_exp.rel_value_us);
-    ns_it = NULL;
-    //finished -> TODO reschedule
-    update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp,
-                                                &update_identities,
-                                                ego_head);
-    min_rel_exp.rel_value_us = 0;
-    return;
-  }
-  priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego);
-  if (GNUNET_YES == next_ego->attributes_dirty)
-  {
-    //Starting over. We must update the Attributes for they might have changed.
-    ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
-                                                   priv_key,
-                                                   &attribute_collect,
-                                                   next_ego);
-
-  }
-  else
-  {
-    //Ego will be dirty next time
-    next_ego->attributes_dirty = GNUNET_YES;
-    ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
-                                                   priv_key,
-                                                   &token_collect,
-                                                   next_ego);
-  }
-}
-
-
-
-/**
- * Function called initially to start update task
- */
-static void
-init_cont ()
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, ">>> Starting Service\n");
-  //Initially iterate all itenties and refresh all tokens
-  update_task = GNUNET_SCHEDULER_add_now (&update_identities, ego_head);
-}
-
-/**
- * Initial ego collection function.
- *
- * @param cls NULL
- * @param ego ego
- * @param ctx context
- * @param identifier ego name
- */
-static void
-list_ego (void *cls,
-          struct GNUNET_IDENTITY_Ego *ego,
-          void **ctx,
-          const char *identifier)
-{
-  struct EgoEntry *new_entry;
-  if ((NULL == ego) && (STATE_INIT == state))
-  {
-    state = STATE_POST_INIT;
-    init_cont ();
-    return;
-  }
-  if (STATE_INIT == state) {
-    new_entry = GNUNET_malloc (sizeof (struct EgoEntry));
-    new_entry->ego = ego;
-    new_entry->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
-                                                                GNUNET_NO);
-    new_entry->attributes_dirty = GNUNET_YES;
-    GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry);
-  }
-}
-
-/**
- * Cleanup task
- */
-static void
-cleanup()
-{
-  struct EgoEntry *ego_entry;
-  struct EgoEntry *ego_tmp;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Cleaning up\n");
-  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 != 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);
-  if (NULL != token)
-    GNUNET_free (token);
-  if (NULL != label)
-    GNUNET_free (label);
-
-  for (ego_entry = ego_head;
-       NULL != ego_entry;)
-  {
-    ego_tmp = ego_entry;
-    if (0 != GNUNET_CONTAINER_multihashmap_size (ego_tmp->attr_map))
-    {
-      GNUNET_CONTAINER_multihashmap_iterate (ego_tmp->attr_map,
-                                             &clear_ego_attrs,
-                                             ego_tmp);
-
-    }
-    GNUNET_CONTAINER_multihashmap_destroy (ego_tmp->attr_map);
-    ego_entry = ego_entry->next;
-    GNUNET_free (ego_tmp);
-  }
-}
-
-/**
- * Shutdown task
- *
- * @param cls NULL
- * @param tc task context
- */
-static void
-do_shutdown (void *cls,
-             const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Shutting down...\n");
-  cleanup();
-}
-
-/**
- * Main function that will be run
- *
- * @param cls closure
- * @param args remaining command-line arguments
- * @param cfgfile name of the configuration file used (for saving, can be NULL)
- * @param c configuration
- */
-static void
-run (void *cls, 
-     char *const *args, 
-     const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  cfg = c;
-
-
-  //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");
-  }
-
-  identity_handle = GNUNET_IDENTITY_connect (cfg,
-                                             &list_ego,
-                                             NULL);
-
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
-                                &do_shutdown, NULL);
-}
-
-
-/**
- *
- * The main function for gnunet-service-identity-token
- *
- * @param argc number of arguments from the cli
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- *
- */
-int
-main (int argc, char *const *argv)
-{
-  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_OPTION_END
-  };
-  int ret;
-
-  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
-    return 2;
-  GNUNET_log_setup ("gnunet-service-identity-token", "WARNING", NULL);
-  ret =
-    (GNUNET_OK ==
-     GNUNET_PROGRAM_run (argc, argv, "gnunet-service-identity-token",
-                         _("GNUnet identity token service"),
-                         options,
-                         &run, NULL)) ? 0: 1;
-  GNUNET_free_non_null ((char *) argv);
-  return ret;
-}
-
-/* end of gnunet-rest-server.c */
diff --git a/src/identity-token/identity-token.c b/src/identity-token/identity-token.c
deleted file mode 100644 (file)
index a9f210b..0000000
+++ /dev/null
@@ -1,827 +0,0 @@
-/*
-      This file is part of GNUnet
-      Copyright (C) 2010-2015 Christian Grothoff (and other contributing authors)
-
-      GNUnet is free software; you can redistribute it and/or modify
-      it under the terms of the GNU General Public License as published
-      by the Free Software Foundation; either version 3, or (at your
-      option) any later version.
-
-      GNUnet is distributed in the hope that it will be useful, but
-      WITHOUT ANY WARRANTY; without even the implied warranty of
-      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-      General Public License for more details.
-
-      You should have received a copy of the GNU General Public License
-      along with GNUnet; see the file COPYING.  If not, write to the
-      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-      Boston, MA 02110-1301, USA.
- */
-
-/**
- * @file identity-token/identity-token.c
- * @brief helper library to manage identity tokens
- * @author Martin Schanzenbach
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_signatures.h"
-#include "gnunet_identity_provider_lib.h"
-#include <jansson.h>
-
-
-/**
- * Crypto helper functions
- */
-
-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_ERROR, "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;
-}
-
-
-
-/**
- * Decrypts metainfo part from a token code
- */
-static int
-decrypt_str_ecdhe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                   const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key,
-                   const char *cyphertext,
-                   size_t cyphertext_len,
-                   char **result_str)
-{
-  struct GNUNET_HashCode new_key_hash;
-  struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
-  struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
-
-  char *str_buf = GNUNET_malloc (cyphertext_len);
-  size_t str_size;
-
-  //Calculate symmetric key from ecdh parameters
-  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_ecdh (priv_key,
-                                                        ecdh_key,
-                                                        &new_key_hash));
-
-  create_sym_key_from_ecdh (&new_key_hash,
-                            &enc_key,
-                            &enc_iv);
-
-  str_size = GNUNET_CRYPTO_symmetric_decrypt (cyphertext,
-                                              cyphertext_len,
-                                              &enc_key,
-                                              &enc_iv,
-                                              str_buf);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Decrypted bytes: %d Expected bytes: %d\n", str_size, cyphertext_len);
-  if (-1 == str_size)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH invalid\n");
-    GNUNET_free (str_buf);
-    return GNUNET_SYSERR;
-  }
-  *result_str = GNUNET_malloc (str_size+1);
-  memcpy (*result_str, str_buf, str_size);
-  (*result_str)[str_size] = '\0';
-  GNUNET_free (str_buf);
-  return GNUNET_OK;
-
-}
-
-/**
- * Decrypt string using pubkey and ECDHE
-*/
-static int
-decrypt_str_ecdhe2 (const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_privkey,
-                    const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-                    const char *ciphertext,
-                    size_t ciphertext_len,
-                    char **plaintext)
-{
-  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
-  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
-  struct GNUNET_HashCode new_key_hash;
-
-  //This is true see documentation for GNUNET_CRYPTO_symmetric_encrypt
-  *plaintext = GNUNET_malloc (ciphertext_len);
-
-  // Derived key K = H(eB)
-  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (ecdh_privkey,
-                                                        aud_key,
-                                                        &new_key_hash));
-  create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
-  GNUNET_CRYPTO_symmetric_decrypt (ciphertext,
-                                   ciphertext_len,
-                                   &skey, &iv,
-                                   *plaintext);
-  return GNUNET_OK;
-}
-
-
-/**
- * Encrypt string using pubkey and ECDHE
- * Returns ECDHE pubkey to be used for decryption
- */
-static int
-encrypt_str_ecdhe (const char *plaintext,
-                   const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key,
-                   char **cyphertext,
-                   struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
-                   struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pubkey)
-{
-  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
-  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
-  struct GNUNET_HashCode new_key_hash;
-  ssize_t enc_size;
-
-  // ECDH keypair E = eG
-  *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
-  GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
-                                      ecdh_pubkey);
-
-  //This is true see documentation for GNUNET_CRYPTO_symmetric_encrypt
-  *cyphertext = GNUNET_malloc (strlen (plaintext));
-
-  // Derived key K = H(eB)
-  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
-                                                        pub_key,
-                                                        &new_key_hash));
-  create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Encrypting string %s\n (len=%d)",
-              plaintext,
-              strlen (plaintext));
-  enc_size = GNUNET_CRYPTO_symmetric_encrypt (plaintext, strlen (plaintext),
-                                              &skey, &iv,
-                                              *cyphertext);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Encrypted (len=%d)", enc_size);
-  return GNUNET_OK;
-}
-
-
-
-
-/**
- * Identity Token API
- */
-
-
-/**
- * Create an Identity Token
- *
- * @param type the JSON API resource type
- * @param id the JSON API resource id
- * @return a new JSON API resource or NULL on error.
- */
-struct GNUNET_IDENTITY_PROVIDER_Token*
-GNUNET_IDENTITY_PROVIDER_token_create (const struct GNUNET_CRYPTO_EcdsaPublicKey* iss,
-                                       const struct GNUNET_CRYPTO_EcdsaPublicKey* aud)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Token *token;
-  char* audience;
-  char* issuer;
-
-  issuer = GNUNET_STRINGS_data_to_string_alloc (iss,
-                                                sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  audience = GNUNET_STRINGS_data_to_string_alloc (aud,
-                                                  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
-
-
-  token = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Token));
-
-  token->header = json_object();
-  token->payload = json_object();
-
-  json_object_set_new (token->header, "alg", json_string ("ED512"));
-  json_object_set_new (token->header, "typ", json_string ("JWT"));
-
-  json_object_set_new (token->payload, "iss", json_string (issuer));
-  json_object_set_new (token->payload, "aud", json_string (audience));
-
-  token->aud_key = *aud;
-  GNUNET_free (issuer);
-  GNUNET_free (audience);
-  return token;
-}
-
-void
-GNUNET_IDENTITY_PROVIDER_token_destroy (struct GNUNET_IDENTITY_PROVIDER_Token *token)
-{
-  json_decref (token->header);
-  json_decref (token->payload);
-  GNUNET_free (token);
-}
-
-void
-GNUNET_IDENTITY_PROVIDER_token_add_attr (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
-                                         const char* key,
-                                         const char* value)
-{
-  GNUNET_assert (NULL != token);
-  GNUNET_assert (NULL != token->payload);
-
-  json_object_set_new (token->payload, key, json_string (value));
-}
-
-void
-GNUNET_IDENTITY_PROVIDER_token_add_json (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
-                                         const char* key,
-                                         json_t* value)
-{
-  GNUNET_assert (NULL != token);
-  GNUNET_assert (NULL != token->payload);
-
-  json_object_set_new (token->payload, key, value);
-}
-
-
-int
-GNUNET_IDENTITY_PROVIDER_token_parse2 (const char* raw_data,
-                                       const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
-                                       const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-                                       struct GNUNET_IDENTITY_PROVIDER_Token **result)
-{
-  char *enc_token_str;
-  char *tmp_buf;
-  char *token_str;
-  char *enc_token;
-  char *header;
-  char *header_base64;
-  char *payload;
-  char *payload_base64;
-  size_t enc_token_len;
-  json_error_t err_json;
-
-  GNUNET_asprintf (&tmp_buf, "%s", raw_data);
-  strtok (tmp_buf, ",");
-  enc_token_str = strtok (NULL, ",");
-
-  enc_token_len = GNUNET_STRINGS_base64_decode (enc_token_str,
-                                                strlen (enc_token_str),
-                                                &enc_token);
-  if (GNUNET_OK != decrypt_str_ecdhe2 (priv_key,
-                                       aud_key,
-                                       enc_token,
-                                       enc_token_len,
-                                       &token_str))
-  {
-    GNUNET_free (tmp_buf);
-    GNUNET_free (enc_token);
-    return GNUNET_SYSERR;
-  }
-
-  header_base64 = strtok (token_str, ".");
-  payload_base64 = strtok (NULL, ".");
-
-  GNUNET_STRINGS_base64_decode (header_base64,
-                                strlen (header_base64),
-                                &header);
-  GNUNET_STRINGS_base64_decode (payload_base64,
-                                strlen (payload_base64),
-                                &payload);
-  //TODO signature
-
-
-  *result = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Token));
-  (*result)->aud_key =  *aud_key;
-  (*result)->header = json_loads (header, JSON_DECODE_ANY, &err_json);
-  (*result)->payload = json_loads (payload, JSON_DECODE_ANY, &err_json);
-  GNUNET_free (enc_token);
-  GNUNET_free (token_str);
-  GNUNET_free (tmp_buf);
-  GNUNET_free (payload);
-  GNUNET_free (header);
-  return GNUNET_OK;
-}
-
-int
-GNUNET_IDENTITY_PROVIDER_token_parse (const char* raw_data,
-                                      const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                                      struct GNUNET_IDENTITY_PROVIDER_Token **result)
-{
-  char *ecdh_pubkey_str;
-  char *enc_token_str;
-  char *tmp_buf;
-  char *token_str;
-  char *enc_token;
-  char *header;
-  char *header_base64;
-  char *payload;
-  char *payload_base64;
-  size_t enc_token_len;
-  json_error_t err_json;
-  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
-
-  GNUNET_asprintf (&tmp_buf, "%s", raw_data);
-  ecdh_pubkey_str = strtok (tmp_buf, ",");
-  enc_token_str = strtok (NULL, ",");
-
-  GNUNET_STRINGS_string_to_data (ecdh_pubkey_str,
-                                 strlen (ecdh_pubkey_str),
-                                 &ecdh_pubkey,
-                                 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
-  enc_token_len = GNUNET_STRINGS_base64_decode (enc_token_str,
-                                                strlen (enc_token_str),
-                                                &enc_token);
-  if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
-                                      &ecdh_pubkey,
-                                      enc_token,
-                                      enc_token_len,
-                                      &token_str))
-  {
-    GNUNET_free (tmp_buf);
-    GNUNET_free (enc_token);
-    return GNUNET_SYSERR;
-  }
-
-  header_base64 = strtok (token_str, ".");
-  payload_base64 = strtok (NULL, ".");
-
-  GNUNET_STRINGS_base64_decode (header_base64,
-                                strlen (header_base64),
-                                &header);
-  GNUNET_STRINGS_base64_decode (payload_base64,
-                                strlen (payload_base64),
-                                &payload);
-  //TODO signature and aud key
-
-
-  *result = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Token));
-  (*result)->header = json_loads (header, JSON_DECODE_ANY, &err_json);
-  (*result)->payload = json_loads (payload, JSON_DECODE_ANY, &err_json);
-  GNUNET_free (enc_token);
-  GNUNET_free (token_str);
-  GNUNET_free (tmp_buf);
-  GNUNET_free (payload);
-  GNUNET_free (header);
-  return GNUNET_OK;
-}
-
-int
-GNUNET_IDENTITY_PROVIDER_token_to_string (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
-                                          const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                                          char **result)
-{
-  char *payload_str;
-  char *header_str;
-  char *payload_base64;
-  char *header_base64;
-  char *padding;
-  char *signature_target;
-  char *signature_str;
-  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-  header_str = json_dumps (token->header, JSON_COMPACT);
-  GNUNET_STRINGS_base64_encode (header_str,
-                                strlen (header_str),
-                                &header_base64);
-  //Remove GNUNET padding of base64
-  padding = strtok(header_base64, "=");
-  while (NULL != padding)
-    padding = strtok(NULL, "=");
-
-  payload_str = json_dumps (token->payload, JSON_COMPACT);
-  GNUNET_STRINGS_base64_encode (payload_str,
-                                strlen (payload_str),
-                                &payload_base64);
-
-  //Remove GNUNET padding of base64
-  padding = strtok(payload_base64, "=");
-  while (NULL != padding)
-    padding = strtok(NULL, "=");
-
-  GNUNET_asprintf (&signature_target, "%s,%s", header_base64, payload_base64);
-  purpose =
-    GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
-                   strlen (signature_target));
-  purpose->size =
-    htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
-  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
-  memcpy (&purpose[1], signature_target, strlen (signature_target));
-  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
-                                             purpose,
-                                             (struct GNUNET_CRYPTO_EcdsaSignature *)&token->signature))
-  {
-    GNUNET_free (signature_target);
-    GNUNET_free (payload_str);
-    GNUNET_free (header_str);
-    GNUNET_free (payload_base64);
-    GNUNET_free (header_base64);
-    GNUNET_free (purpose);
-    return GNUNET_SYSERR;
-  }
-
-  GNUNET_STRINGS_base64_encode ((const char*)&token->signature,
-                                sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
-                                &signature_str);
-  GNUNET_asprintf (result, "%s.%s.%s",
-                   header_base64, payload_base64, signature_str);
-  GNUNET_free (signature_target);
-  GNUNET_free (payload_str);
-  GNUNET_free (header_str);
-  GNUNET_free (signature_str);
-  GNUNET_free (payload_base64);
-  GNUNET_free (header_base64);
-  GNUNET_free (purpose);
-  return GNUNET_OK;
-}
-
-int
-GNUNET_IDENTITY_PROVIDER_token_serialize (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
-                                          const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                                          struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
-                                          char **result)
-{
-  char *token_str;
-  char *enc_token;
-  char *dh_key_str;
-  char *enc_token_base64;
-  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
-
-  GNUNET_assert (GNUNET_OK == GNUNET_IDENTITY_PROVIDER_token_to_string (token,
-                                                                        priv_key,
-                                                                        &token_str));
-
-  GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (token_str,
-                                                 &token->aud_key,
-                                                 &enc_token,
-                                                 ecdh_privkey,
-                                                 &ecdh_pubkey));
-  GNUNET_STRINGS_base64_encode (enc_token,
-                                strlen (token_str),
-                                &enc_token_base64);
-  dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ecdh_pubkey,
-                                                    sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
-  GNUNET_asprintf (result, "%s,%s", dh_key_str, enc_token_base64);
-  GNUNET_free (dh_key_str);
-  GNUNET_free (enc_token_base64);
-  GNUNET_free (enc_token);
-  GNUNET_free (token_str);
-  return GNUNET_OK;
-}
-
-struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload*
-GNUNET_IDENTITY_PROVIDER_ticket_payload_create (const char* nonce,
-                                                const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
-                                                const char* lbl_str)
-{
-  struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload* payload;
-
-  payload = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload));
-  GNUNET_asprintf (&payload->nonce, nonce, strlen (nonce));
-  payload->identity_key = *identity_pkey;
-  GNUNET_asprintf (&payload->label, lbl_str, strlen (lbl_str));
-  return payload;
-}
-
-void
-GNUNET_IDENTITY_PROVIDER_ticket_payload_destroy (struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload* payload)
-{
-  GNUNET_free (payload->nonce);
-  GNUNET_free (payload->label);
-  GNUNET_free (payload);
-}
-
-void
-GNUNET_IDENTITY_PROVIDER_ticket_payload_serialize (struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload *payload,
-                                                   char **result)
-{
-  char* identity_key_str;
-
-  identity_key_str = GNUNET_STRINGS_data_to_string_alloc (&payload->identity_key,
-                                                          sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
-  GNUNET_asprintf (result, 
-                   "{\"nonce\": \"%u\",\"identity\": \"%s\",\"label\": \"%s\"}",
-                   payload->nonce, identity_key_str, payload->label);
-  GNUNET_free (identity_key_str);
-
-}
-
-
-/**
- * Create the token code
- * The metadata is encrypted with a share ECDH derived secret using B (aud_key)
- * and e (ecdh_privkey)
- * The ticket also contains E (ecdh_pubkey) and a signature over the
- * metadata and E
- */
-struct GNUNET_IDENTITY_PROVIDER_TokenTicket*
-GNUNET_IDENTITY_PROVIDER_ticket_create (const char* nonce_str,
-                                        const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
-                                        const char* lbl_str,
-                                        const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key)
-{
-  struct GNUNET_IDENTITY_PROVIDER_TokenTicket *ticket;
-  struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload *code_payload;
-
-  ticket = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_TokenTicket));
-  code_payload = GNUNET_IDENTITY_PROVIDER_ticket_payload_create (nonce_str,
-                                                                 identity_pkey,
-                                                                 lbl_str);
-  ticket->aud_key = *aud_key;
-  ticket->payload = code_payload;
-
-
-  return ticket;
-}
-
-void
-GNUNET_IDENTITY_PROVIDER_ticket_destroy (struct GNUNET_IDENTITY_PROVIDER_TokenTicket *ticket)
-{
-  GNUNET_IDENTITY_PROVIDER_ticket_payload_destroy (ticket->payload);
-  GNUNET_free (ticket);
-}
-
-int
-GNUNET_IDENTITY_PROVIDER_ticket_serialize (struct GNUNET_IDENTITY_PROVIDER_TokenTicket *ticket,
-                                           const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                                           char **result)
-{
-  char *code_payload_str;
-  char *enc_ticket_payload;
-  char *ticket_payload_str;
-  char *ticket_sig_str;
-  char *ticket_str;
-  char *dh_key_str;
-  char *write_ptr;
-  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
-
-  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-
-  GNUNET_IDENTITY_PROVIDER_ticket_payload_serialize (ticket->payload,
-                                                     &code_payload_str);
-
-  GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (code_payload_str,
-                                                 &ticket->aud_key,
-                                                 &enc_ticket_payload,
-                                                 &ecdhe_privkey,
-                                                 &ticket->ecdh_pubkey));
-
-  GNUNET_free (ecdhe_privkey);
-
-  purpose = 
-    GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 
-                   sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
-                   strlen (code_payload_str)); // E_K (code_str)
-  purpose->size = 
-    htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
-           sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
-           strlen (code_payload_str));
-  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
-  write_ptr = (char*) &purpose[1];
-  memcpy (write_ptr,
-          &ticket->ecdh_pubkey,
-          sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
-  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
-  memcpy (write_ptr, enc_ticket_payload, strlen (code_payload_str));
-  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign (priv_key,
-                                                        purpose,
-                                                       &ticket->signature));
-  GNUNET_STRINGS_base64_encode (enc_ticket_payload,
-                                strlen (code_payload_str),
-                                &ticket_payload_str);
-  ticket_sig_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->signature,
-                                                        sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
-
-  dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->ecdh_pubkey,
-                                                    sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Using ECDH pubkey %s to encrypt\n", dh_key_str);
-  GNUNET_asprintf (&ticket_str, "{\"meta\": \"%s\", \"ecdh\": \"%s\", \"signature\": \"%s\"}",
-                   ticket_payload_str, dh_key_str, ticket_sig_str);
-  GNUNET_STRINGS_base64_encode (ticket_str, strlen (ticket_str), result);
-  GNUNET_free (dh_key_str);
-  GNUNET_free (purpose);
-  GNUNET_free (ticket_str);
-  GNUNET_free (ticket_sig_str);
-  GNUNET_free (code_payload_str);
-  GNUNET_free (enc_ticket_payload);
-  GNUNET_free (ticket_payload_str);
-  return GNUNET_OK;
-}
-
-int
-GNUNET_IDENTITY_PROVIDER_ticket_payload_parse(const char *raw_data,
-                                              ssize_t data_len,
-                                              const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                                              const struct GNUNET_CRYPTO_EcdhePublicKey *ecdhe_pkey,
-                                              struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload **result)
-{
-  const char* label_str;
-  const char* nonce_str;
-  const char* identity_key_str;
-
-  json_t *root;
-  json_t *label_json;
-  json_t *identity_json;
-  json_t *nonce_json;
-  json_error_t err_json;
-  char* meta_str;
-  struct GNUNET_CRYPTO_EcdsaPublicKey id_pkey;
-
-  if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
-                                      ecdhe_pkey,
-                                      raw_data,
-                                      data_len,
-                                      &meta_str))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Metadata decryption failed\n");
-    return GNUNET_SYSERR;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Metadata: %s\n", meta_str);
-  root = json_loads (meta_str, JSON_DECODE_ANY, &err_json);
-  if (!root)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error parsing metadata: %s\n", err_json.text);
-    GNUNET_free (meta_str);
-    return GNUNET_SYSERR;
-  }
-
-  identity_json = json_object_get (root, "identity");
-  if (!json_is_string (identity_json))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error parsing metadata: %s\n", err_json.text);
-    json_decref (root);
-    GNUNET_free (meta_str);
-    return GNUNET_SYSERR;
-  }
-  identity_key_str = json_string_value (identity_json);
-  GNUNET_STRINGS_string_to_data (identity_key_str,
-                                 strlen (identity_key_str),
-                                 &id_pkey,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
-
-  label_json = json_object_get (root, "label");
-  if (!json_is_string (label_json))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error parsing metadata: %s\n", err_json.text);
-    json_decref (root);
-    GNUNET_free (meta_str);
-    return GNUNET_SYSERR;
-  }
-
-  label_str = json_string_value (label_json);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Found label: %s\n", label_str);
-
-  nonce_json = json_object_get (root, "nonce");
-  if (!json_is_string (label_json))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error parsing metadata: %s\n", err_json.text);
-    json_decref (root);
-    GNUNET_free (meta_str);
-    return GNUNET_SYSERR;
-  }
-
-  nonce_str = json_string_value (nonce_json);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Found nonce: %s\n", nonce_str);
-
-  *result = GNUNET_IDENTITY_PROVIDER_ticket_payload_create (nonce_str,
-                                                            (const struct GNUNET_CRYPTO_EcdsaPublicKey*)&id_pkey,
-                                                            label_str);
-  GNUNET_free (meta_str);
-  json_decref (root);
-  return GNUNET_OK;
-
-}
-
-int
-GNUNET_IDENTITY_PROVIDER_ticket_parse (const char *raw_data,
-                                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                                       struct GNUNET_IDENTITY_PROVIDER_TokenTicket **result)
-{
-  const char* enc_meta_str;
-  const char* ecdh_enc_str;
-  const char* signature_enc_str;
-
-  json_t *root;
-  json_t *signature_json;
-  json_t *ecdh_json;
-  json_t *enc_meta_json;
-  json_error_t err_json;
-  char* enc_meta;
-  char* ticket_decoded;
-  char* write_ptr;
-  size_t enc_meta_len;
-  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-  struct GNUNET_IDENTITY_PROVIDER_TokenTicket *ticket;
-  struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload *ticket_payload;
-
-  ticket_decoded = NULL;
-  GNUNET_STRINGS_base64_decode (raw_data, strlen (raw_data), &ticket_decoded);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Token Code: %s\n", ticket_decoded);
-  root = json_loads (ticket_decoded, JSON_DECODE_ANY, &err_json);
-  if (!root)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "%s\n", err_json.text);
-    return GNUNET_SYSERR;
-  }
-
-  signature_json = json_object_get (root, "signature");
-  ecdh_json = json_object_get (root, "ecdh");
-  enc_meta_json = json_object_get (root, "meta");
-
-  signature_enc_str = json_string_value (signature_json);
-  ecdh_enc_str = json_string_value (ecdh_json);
-  enc_meta_str = json_string_value (enc_meta_json);
-
-  ticket = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_TokenTicket));
-
-  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ecdh_enc_str,
-                                                  strlen (ecdh_enc_str),
-                                                  &ticket->ecdh_pubkey,
-                                                  sizeof  (struct GNUNET_CRYPTO_EcdhePublicKey)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH PKEY %s invalid in metadata\n", ecdh_enc_str);
-    json_decref (root);
-    GNUNET_free (ticket);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Using ECDH pubkey %s for metadata decryption\n", ecdh_enc_str);
-  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_enc_str,
-                                                  strlen (signature_enc_str),
-                                                  &ticket->signature,
-                                                  sizeof (struct GNUNET_CRYPTO_EcdsaSignature)))
-  {
-    json_decref (root);
-    GNUNET_free (ticket_decoded);
-    GNUNET_free (ticket);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH signature invalid in metadata\n");
-    return GNUNET_SYSERR;
-  }
-
-  enc_meta_len = GNUNET_STRINGS_base64_decode (enc_meta_str,
-                                               strlen (enc_meta_str),
-                                               &enc_meta);
-
-
-  GNUNET_IDENTITY_PROVIDER_ticket_payload_parse (enc_meta,
-                                                 enc_meta_len,
-                                                 priv_key,
-                                                 (const struct GNUNET_CRYPTO_EcdhePublicKey*)&ticket->ecdh_pubkey,
-                                                 &ticket_payload);
-
-  ticket->payload = ticket_payload;
-  //TODO: check signature here
-  purpose = 
-    GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 
-                   sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
-                   enc_meta_len); // E_K (code_str)
-  purpose->size = 
-    htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
-           sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
-           enc_meta_len);
-  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
-  write_ptr = (char*) &purpose[1];
-  memcpy (write_ptr, &ticket->ecdh_pubkey, sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
-  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
-  memcpy (write_ptr, enc_meta, enc_meta_len);
-
-  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET,
-                                               purpose,
-                                               &ticket->signature,
-                                               &ticket_payload->identity_key))
-  {
-    GNUNET_IDENTITY_PROVIDER_ticket_destroy (ticket);
-    GNUNET_free (ticket_decoded);
-    json_decref (root);
-    GNUNET_free (purpose);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error verifying signature for token code\n");
-    return GNUNET_SYSERR;
-  }
-  *result = ticket;
-  GNUNET_free (purpose);
-
-  GNUNET_free (enc_meta);
-  GNUNET_free (ticket_decoded);
-  json_decref (root);
-  return GNUNET_OK;
-
-}
-
-
-
-/* end of identity-token.c */
diff --git a/src/identity-token/identity-token.conf b/src/identity-token/identity-token.conf
deleted file mode 100644 (file)
index f29f6cd..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-[identity-token]
-BINARY=gnunet-service-identity-token
diff --git a/src/identity-token/identity-token.h b/src/identity-token/identity-token.h
deleted file mode 100644 (file)
index 6e41a00..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 Christian Grothoff (and other contributing authors)
-
-   GNUnet is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published
-   by the Free Software Foundation; either version 3, or (at your
-   option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GNUnet; see the file COPYING.  If not, write to the
-   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.
-   */
-/**
- * @author Martin Schanzenbach
- * @file include/gnunet_identity_provider_lib.h
- * @brief GNUnet Identity Provider library
- *
- */
-#ifndef GNUNET_IDENTITY_PROVIDER_LIB_H
-#define GNUNET_IDENTITY_PROVIDER_LIB_H
-
-#include "gnunet_crypto_lib.h"
-#include <jansson.h>
-
-struct GNUNET_IDENTITY_PROVIDER_Token
-{
-  /**
-   * JSON header
-   */
-  json_t *header;
-
-  /**
-   * JSON Payload
-   */
-  json_t *payload;
-
-  /**
-   * Token Signature
-   */
-  struct GNUNET_CRYPTO_EcdsaSignature signature;
-  
-  /**
-   * Audience Pubkey
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
-};
-
-struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload
-{
-  /**
-   * Nonce
-   */
-  char* nonce;
-
-  /**
-   * Label
-   */
-  char *label;
-
-  /**
-   * Issuing Identity
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey identity_key;
-};
-
-
-struct GNUNET_IDENTITY_PROVIDER_TokenTicket
-{
-  /**
-   * Meta info
-   */
-  struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload *payload;
-
-  /**
-   * ECDH Pubkey
-   */
-  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
-
-  /**
-   * Signature
-   */
-  struct GNUNET_CRYPTO_EcdsaSignature signature;
-
-  /**
-   * Target identity
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
-};
-
-
-
-/**
- * Create an identity token
- *
- * @param iss the issuer string for the token
- * @param aud the audience of the token
- *
- * @return a new token
- */
-struct GNUNET_IDENTITY_PROVIDER_Token*
-GNUNET_IDENTITY_PROVIDER_token_create (const struct GNUNET_CRYPTO_EcdsaPublicKey *iss,
-                                       const struct GNUNET_CRYPTO_EcdsaPublicKey* aud);
-
-/**
- * Destroy an identity token
- *
- * @param token the token to destroy
- */
-void
-GNUNET_IDENTITY_PROVIDER_token_destroy (struct GNUNET_IDENTITY_PROVIDER_Token *token);
-
-/**
- * Add a new key value pair to the token
- * 
- * @param token the token to modify
- * @param key the key
- * @param value the value
- */
-void
-GNUNET_IDENTITY_PROVIDER_token_add_attr (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
-                                         const char* key,
-                                         const char* value);
-
-/**
- * Add a new key value pair to the token with the value as json
- *
- * @param the token to modify
- * @param key the key
- * @param value the value
- *
- */
-void
-GNUNET_IDENTITY_PROVIDER_token_add_json (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
-                         const char* key,
-                         json_t* value);
-
-/**
- * Serialize a token. The token will be signed and base64 according to the
- * JWT format. The signature is base32-encoded ECDSA.
- * The resulting JWT is encrypted using 
- * ECDHE for the audience and Base64
- * encoded in result. The audience requires the ECDHE public key P 
- * to decrypt the token T. The key P is included in the result and prepended
- * before the token
- *
- * @param token the token to serialize
- * @param priv_key the private key used to sign the token
- * @param ecdhe_privkey the ECDHE private key used to encrypt the token
- * @param result P,Base64(E(T))
- *
- * @return GNUNET_OK on success
- */
-int 
-GNUNET_IDENTITY_PROVIDER_token_serialize (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
-                          const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                          struct GNUNET_CRYPTO_EcdhePrivateKey **ecdhe_privkey,
-                          char **result);
-
-/**
- * Parses the serialized token and returns a token
- *
- * @param data the serialized token
- * @param priv_key the private key of the audience
- * @param result the token
- *
- * @return GNUNET_OK on success
- */
-int
-GNUNET_IDENTITY_PROVIDER_token_parse (const char* data,
-                      const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                      struct GNUNET_IDENTITY_PROVIDER_Token **result);
-
-/**
- * Parses the serialized token and returns a token
- * This variant is intended for the party that issued the token and also
- * wants to decrypt the serialized token.
- *
- * @param data the serialized token
- * @param priv_key the private (!) ECDHE key
- * @param aud_key the identity of the audience
- * @param result the token
- *
- * @return GNUNET_OK on success
- */
-int
-GNUNET_IDENTITY_PROVIDER_token_parse2 (const char* data,
-                       const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
-                       const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-                       struct GNUNET_IDENTITY_PROVIDER_Token **result);
-
-
-/**
- *
- * Returns a JWT-string representation of the token
- *
- * @param token the token
- * @param priv_key the private key used to sign the JWT
- * @param result the JWT
- *
- * @return GNUNET_OK on success
- */
-int
-GNUNET_IDENTITY_PROVIDER_token_to_string (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
-                          const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                          char **result);
-
-/**
- *
- * Creates a ticket that can be exchanged by the audience for 
- * the token. The token must be placed under the label
- *
- * @param nonce_str nonce provided by the audience that requested the ticket
- * @param iss_pkey the issuer pubkey used to sign the ticket
- * @param label the label encoded in the ticket
- * @param aud_ley the audience pubkey used to encrypt the ticket payload
- *
- * @return the ticket
- */
-struct GNUNET_IDENTITY_PROVIDER_TokenTicket*
-GNUNET_IDENTITY_PROVIDER_ticket_create (const char* nonce_str,
-                            const struct GNUNET_CRYPTO_EcdsaPublicKey* iss_pkey,
-                            const char* lbl_str,
-                            const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key);
-
-/**
- * Serialize a ticket. Returns the Base64 representation of the ticket.
- * Format: Base64( { payload: E(Payload), ecdhe: K, signature: signature } )
- *
- * @param ticket the ticket to serialize
- * @param priv_key the issuer private key to sign the ticket payload
- * @param result the serialized ticket
- *
- * @return GNUNET_OK on success
- */
-int
-GNUNET_IDENTITY_PROVIDER_ticket_serialize (struct GNUNET_IDENTITY_PROVIDER_TokenTicket *ticket,
-                               const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                               char **result);
-
-/**
- * Destroys a ticket
- *
- * @param the ticket to destroy
- */
-void
-GNUNET_IDENTITY_PROVIDER_ticket_destroy (struct GNUNET_IDENTITY_PROVIDER_TokenTicket *ticket);
-
-/**
- * Parses a serialized ticket
- *
- * @param data the serialized ticket
- * @param priv_key the audience private key
- * @param ticket the ticket
- *
- * @return GNUNET_OK on success
- */
-int
-GNUNET_IDENTITY_PROVIDER_ticket_parse (const char* raw_data,
-                           const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                           struct GNUNET_IDENTITY_PROVIDER_TokenTicket **ticket);
-
-#endif
diff --git a/src/identity-token/plugin_rest_identity_token.c b/src/identity-token/plugin_rest_identity_token.c
deleted file mode 100644 (file)
index d2c1b6c..0000000
+++ /dev/null
@@ -1,1412 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 Christian Grothoff (and other contributing authors)
-
-   GNUnet is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published
-   by the Free Software Foundation; either version 3, or (at your
-   option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GNUnet; see the file COPYING.  If not, write to the
-   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.
-   */
-/**
- * @author Martin Schanzenbach
- * @file 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 "microhttpd.h"
-#include <jansson.h>
-#include "gnunet_signatures.h"
-#include "gnunet_identity_provider_lib.h"
-
-/**
- * REST root namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY_TOKEN "/gnuid"
-
-/**
- * Issue namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE "/gnuid/issue"
-
-/**
- * Check namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK "/gnuid/check"
-
-/**
- * Token namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN "/gnuid/token"
-
-/**
- * Authorize namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY_OAUTH2_AUTHORIZE "/gnuid/authorize"
-
-#define GNUNET_REST_JSONAPI_IDENTITY_token_ticket "code"
-
-#define GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_GRANT_TYPE_CODE "authorization_code"
-
-#define GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_GRANT_TYPE "grant_type"
-
-#define GNUNET_IDENTITY_TOKEN_REQUEST_NONCE "nonce"
-
-/**
- * State while collecting all egos
- */
-#define ID_REST_STATE_INIT 0
-
-/**
- * Done collecting egos
- */
-#define ID_REST_STATE_POST_INIT 1
-
-/**
- * Resource type
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_TOKEN "token"
-
-/**
- * URL parameter to create a GNUid token for a specific audience
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST "audience"
-
-/**
- * URL parameter to create a GNUid token for a specific issuer (EGO)
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST "issuer"
-
-/**
- * Attributes passed to issue request
- */
-#define GNUNET_IDENTITY_TOKEN_ATTR_LIST "requested_attrs"
-
-/**
- * Token expiration string
- */
-#define GNUNET_IDENTITY_TOKEN_EXP_STRING "expiration"
-
-/**
- * Renew token w/ relative expirations
- */
-#define GNUNET_IDENTITY_TOKEN_RENEW_TOKEN "renew_token"
-
-/**
- * Error messages
- */
-#define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid"
-#define GNUNET_REST_ERROR_NO_DATA "No data"
-
-/**
- * GNUid token lifetime
- */
-#define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000
-
-/**
- * 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;
-  
-  /**
-   * Ptr to current ego private key
-   */
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-
-  /**
-   * Handle to the rest connection
-   */
-  struct RestConnectionDataHandle *conndata_handle;
-  
-  /**
-   * The processing state
-   */
-  int state;
-
-  /**
-   * Handle to Identity service.
-   */
-  struct GNUNET_IDENTITY_Handle *identity_handle;
-
-  /**
-   * IDENTITY Operation
-   */
-  struct GNUNET_IDENTITY_Operation *op;
-
-  /**
-   * Handle to NS service
-   */
-  struct GNUNET_NAMESTORE_Handle *ns_handle;
-
-  /**
-   * Handle to GNS service
-   */
-  struct GNUNET_GNS_Handle *gns_handle;
-
-  /**
-   * NS iterator
-   */
-  struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
-
-  /**
-   * NS Handle
-   */
-  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
-
-  /**
-   * 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;    
-  
-  /**
-   * GNS lookup
-   */
-  struct GNUNET_GNS_LookupRequest *lookup_request;
-
-  /**
-   * The plugin result processor
-   */
-  GNUNET_REST_ResultProcessor proc;
-
-  /**
-   * The closure of the result processor
-   */
-  void *proc_cls;
-
-  /**
-   * The name to look up
-   */
-  char *name;
-
-  /**
-   * The url
-   */
-  char *url;
-
-  /**
-   * The data from the REST request
-   */
-  const char* data;
-
-  /**
-   * the length of the REST data
-   */
-  size_t data_size;
-
-  /**
-   * HTTP method
-   */
-  const char* method;
-
-  /**
-   * Error response message
-   */
-  char *emsg;
-
-  /**
-   * Identity Token
-   */
-  struct GNUNET_IDENTITY_PROVIDER_Token *token;
-
-  /**
-   * Identity Token Code
-   */
-  struct GNUNET_IDENTITY_PROVIDER_TokenTicket *token_ticket;
-
-  /**
-   * Response object
-   */
-  struct JsonApiObject *resp_object;
-
-  /**
-   * ID Attribute list given
-   */
-  struct GNUNET_CONTAINER_MultiHashMap *attr_map;
-
-
-};
-
-
-/**
- * Cleanup lookup handle
- * @param handle Handle to clean up
- */
-static void
-cleanup_handle (struct RequestHandle *handle)
-{
-  struct EgoEntry *ego_entry;
-  struct EgoEntry *ego_tmp;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Cleaning up\n");
-  if (NULL != handle->resp_object) 
-    GNUNET_REST_jsonapi_object_delete (handle->resp_object);
-  if (NULL != handle->name)
-    GNUNET_free (handle->name);
-  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->gns_handle)
-    GNUNET_GNS_disconnect (handle->gns_handle);
-  if (NULL != handle->ns_it)
-    GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
-  if (NULL != handle->ns_qe)
-    GNUNET_NAMESTORE_cancel (handle->ns_qe);
-  if (NULL != handle->ns_handle)
-    GNUNET_NAMESTORE_disconnect (handle->ns_handle);
-  if (NULL != handle->attr_map)
-    GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map);
-  if (NULL != handle->token)
-    GNUNET_IDENTITY_PROVIDER_token_destroy (handle->token);
-  if (NULL != handle->token_ticket)
-    GNUNET_IDENTITY_PROVIDER_ticket_destroy (handle->token_ticket);
-  if (NULL != handle->url)
-    GNUNET_free (handle->url);
-  if (NULL != handle->emsg)
-    GNUNET_free (handle->emsg);
-  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);
-  }
-  GNUNET_free (handle);
-}
-
-
-/**
- * Task run on shutdown.  Cleans up everything.
- *
- * @param cls unused
- * @param tc scheduler context
- */
-static void
-do_error (void *cls,
-          const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  char *json_error;
-
-  GNUNET_asprintf (&json_error,
-                   "{Error while processing request: %s}",
-                   handle->emsg);
-
-  resp = GNUNET_REST_create_json_response (json_error);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
-  cleanup_handle (handle);
-  GNUNET_free (json_error);
-}
-
-/**
- * Task run on shutdown.  Cleans up everything.
- *
- * @param cls unused
- * @param tc scheduler context
- */
-static void
-do_cleanup_handle_delayed (void *cls,
-          const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct RequestHandle *handle = cls;
-  cleanup_handle(handle);
-}
-
-void
-store_token_cont (void *cls,
-                  int32_t success,
-                  const char *emsg)
-{
-  char *result_str;
-  struct MHD_Response *resp;
-  struct RequestHandle *handle = cls;
-  
-  handle->ns_qe = NULL;
-  if (GNUNET_SYSERR == success)
-  {
-    handle->emsg = GNUNET_strdup (emsg);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  GNUNET_REST_jsonapi_data_serialize (handle->resp_object, &result_str);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
-  resp = GNUNET_REST_create_json_response (result_str);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_free (result_str);
-  GNUNET_SCHEDULER_add_now (&do_cleanup_handle_delayed, handle);
-}
-
-
-
-
-
-
-
-
-
-/**
- * Build a GNUid token for identity
- * @param handle the handle
- * @param ego_entry the ego to build the token for
- * @param name name of the ego
- * @param token_aud token audience
- * @param token the resulting gnuid token
- * @return identifier string of token (label)
- */
-static void
-sign_and_return_token (void *cls,
-                       const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
-  struct GNUNET_CRYPTO_EcdsaPublicKey aud_pkey;
-  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
-  struct JsonApiResource *json_resource;
-  struct RequestHandle *handle = cls;
-  struct GNUNET_GNSRECORD_Data token_record[2];
-  struct GNUNET_HashCode key;
-  struct GNUNET_TIME_Relative etime_rel;
-  json_t *token_str;
-  json_t *name_str;
-  json_t *token_ticket_json;
-  char *lbl_str;
-  char *exp_str;
-  char *token_ticket_str;
-  char *audience;
-  char *nonce_str;
-  char *enc_token_str;
-  char *token_metadata;
-  char *scopes;
-  char* write_ptr;
-  uint64_t time;
-  uint64_t exp_time;
-  uint64_t rnd_key;
-  size_t token_metadata_len;
-
-  //Remote nonce 
-  nonce_str = NULL;
-  GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE,
-                      strlen (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE),
-                      &key);
-  if ( GNUNET_YES !=
-       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
-                                               &key) )
-  {
-    handle->emsg = GNUNET_strdup ("Request nonce missing!\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
-                                                 &key);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str);
-  //Token audience
-  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST,
-                      strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST),
-                      &key);
-  audience = NULL;
-  if ( GNUNET_YES !=
-       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
-                                               &key) )
-  {
-    handle->emsg = GNUNET_strdup ("Audience missing!\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
-                                                &key);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Audience to issue token for: %s\n", audience);
-
-  //Audience pubkey (B = bG)
-  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (audience,
-                                                               strlen (audience),
-                                                               &aud_pkey))
-  {
-    handle->emsg = GNUNET_strdup ("Client PKEY invalid!\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-
-  rnd_key = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
-  GNUNET_STRINGS_base64_encode ((char*)&rnd_key, sizeof (uint64_t), &lbl_str);
-  priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego);
-  GNUNET_CRYPTO_ecdsa_key_get_public (priv_key,
-                                      &pub_key);
-
-  handle->token_ticket = GNUNET_IDENTITY_PROVIDER_ticket_create (nonce_str,
-                                                   &pub_key,
-                                                   lbl_str,
-                                                   &aud_pkey);
-
-  if (GNUNET_OK != GNUNET_IDENTITY_PROVIDER_ticket_serialize (handle->token_ticket,
-                                                  priv_key,
-                                                  &token_ticket_str))
-  {
-    handle->emsg = GNUNET_strdup ("Unable to create ref token!\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING,
-                      strlen (GNUNET_IDENTITY_TOKEN_EXP_STRING),
-                      &key);
-  //Get expiration for token from URL parameter
-  exp_str = NULL;
-  if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
-                                                            &key))
-  {
-    exp_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
-                                                 &key);
-  }
-  if (NULL == exp_str) {
-    handle->emsg = GNUNET_strdup ("No expiration given!\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_STRINGS_fancy_time_to_relative (exp_str,
-                                             &etime_rel))
-  {
-    handle->emsg = GNUNET_strdup ("Expiration invalid!\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  time = GNUNET_TIME_absolute_get().abs_value_us;
-  exp_time = time + etime_rel.rel_value_us;
-
-  //json_object_set_new (handle->payload, "lbl", json_string (lbl_str));
-  GNUNET_IDENTITY_PROVIDER_token_add_attr (handle->token, "sub", handle->ego_entry->identifier);
-  GNUNET_IDENTITY_PROVIDER_token_add_json (handle->token, "nbf", json_integer (time));
-  GNUNET_IDENTITY_PROVIDER_token_add_json (handle->token, "iat", json_integer (time));
-  GNUNET_IDENTITY_PROVIDER_token_add_json (handle->token, "exp", json_integer (exp_time));
-  GNUNET_IDENTITY_PROVIDER_token_add_attr (handle->token, "nonce", nonce_str);
-
-  
-  handle->resp_object = GNUNET_REST_jsonapi_object_new ();
-
-  json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
-                                                    lbl_str);
-  name_str = json_string (handle->ego_entry->identifier);
-  GNUNET_REST_jsonapi_resource_add_attr (json_resource,
-                                         GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
-                                         name_str);
-  json_decref (name_str);
-  token_str = json_string (enc_token_str);
-  GNUNET_REST_jsonapi_resource_add_attr (json_resource,                                         
-                                         GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
-                                         token_str);
-  token_ticket_json = json_string (token_ticket_str);
-  GNUNET_REST_jsonapi_resource_add_attr (json_resource,
-                                         GNUNET_REST_JSONAPI_IDENTITY_token_ticket,
-                                         token_ticket_json);
-  GNUNET_free (token_ticket_str);
-  json_decref (token_ticket_json);
-  GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource);
-  //Token in a serialized encrypted format 
-  GNUNET_assert (GNUNET_IDENTITY_PROVIDER_token_serialize (handle->token,
-                                                           priv_key,
-                                                           &ecdhe_privkey,
-                                                           &enc_token_str));
-
-  //Token record E,E_K (Token)
-  token_record[0].data = enc_token_str;
-  token_record[0].data_size = strlen (enc_token_str) + 1;
-  token_record[0].expiration_time = exp_time;
-  token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN;
-  token_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
-
-
-  //Meta info
-  GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_ATTR_LIST,
-                      strlen (GNUNET_IDENTITY_TOKEN_ATTR_LIST),
-                      &key);
-
-  scopes = NULL;
-  if ( GNUNET_YES !=
-       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
-                                               &key) )
-  {
-    handle->emsg = GNUNET_strdup ("Scopes missing!\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  scopes = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
-                                              &key);
-
-  token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
-    + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
-    + strlen (scopes) + 1; //With 0-Terminator
-  token_metadata = GNUNET_malloc (token_metadata_len);
-  write_ptr = token_metadata;
-  memcpy (token_metadata, ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
-  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
-  memcpy (write_ptr, &aud_pkey, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
-  memcpy (write_ptr, scopes, strlen (scopes) + 1); //with 0-Terminator;
-
-  GNUNET_free (ecdhe_privkey);
-
-  token_record[1].data = token_metadata;
-  token_record[1].data_size = token_metadata_len;
-  token_record[1].expiration_time = exp_time;
-  token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
-  token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
-
-  //Persist token
-  handle->ns_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
-                                                  priv_key,
-                                                  lbl_str,
-                                                  2,
-                                                  token_record,
-                                                  &store_token_cont,
-                                                  handle);
-  GNUNET_free (lbl_str);
-  GNUNET_free (enc_token_str);
-  json_decref (token_str);
-}
-
-
-
-
-
-static void
-attr_collect (void *cls,
-              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-              const char *label,
-              unsigned int rd_count,
-              const struct GNUNET_GNSRECORD_Data *rd)
-{
-  int i;
-  char* data;
-  json_t *attr_arr;
-  struct RequestHandle *handle = cls;
-  struct GNUNET_HashCode key;
-
-  if (NULL == label)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n");
-    handle->ns_it = NULL;
-    GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
-    return;
-  }
-
-  GNUNET_CRYPTO_hash (label,
-                      strlen (label),
-                      &key);
-
-  if (0 == rd_count ||
-      ( (NULL != handle->attr_map) &&
-        (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map,
-                                                               &key))
-      )
-     )
-  {
-    GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", label);
-
-  if (1 == rd_count)
-  {
-    if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
-    {
-      data = GNUNET_GNSRECORD_value_to_string (rd->record_type,
-                                               rd->data,
-                                               rd->data_size);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
-      GNUNET_IDENTITY_PROVIDER_token_add_attr (handle->token, label, data);
-      GNUNET_free (data);
-    }
-    GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
-    return;
-  }
-
-  i = 0;
-  attr_arr = json_array();
-  for (; i < rd_count; i++)
-  {
-    if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
-    {
-      data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
-                                               rd[i].data,
-                                               rd[i].data_size);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
-      json_array_append_new (attr_arr, json_string (data));
-      GNUNET_free (data);
-    }
-  }
-
-  if (0 < json_array_size (attr_arr))
-  {
-    GNUNET_IDENTITY_PROVIDER_token_add_json (handle->token, label, attr_arr);
-  }
-  json_decref (attr_arr);
-  GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
-}
-
-
-/**
- * Create a response with requested ego(s)
- *
- * @param con the Rest handle
- * @param url the requested url
- * @param cls the request handle
- */
-static void
-issue_token_cont (struct RestConnectionDataHandle *con,
-                  const char *url,
-                  void *cls)
-{
-  const char *egoname;
-  char *ego_val;
-  char *audience;
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct GNUNET_HashCode key;
-  struct MHD_Response *resp;
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
-  struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
-
-  if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url,
-                                                GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "URL invalid: %s\n", handle->url);
-    resp = GNUNET_REST_create_json_response (NULL);
-    handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
-    cleanup_handle (handle);
-    return;
-  }
-
-  egoname = NULL;
-  ego_entry = NULL;
-  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
-                      strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
-                      &key);
-  if ( GNUNET_YES ==
-       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
-                                               &key) )
-  {
-    ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
-                                                 &key);
-    if (NULL == ego_val)
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Ego invalid: %s\n", ego_val);
-    if (NULL != ego_val)
-    {
-      for (ego_entry = handle->ego_head;
-           NULL != ego_entry;
-           ego_entry = ego_entry->next)
-      {
-        if (0 != strcmp (ego_val, ego_entry->identifier))
-          continue;
-        egoname = ego_entry->identifier;
-        break;
-      }
-      if (NULL == egoname || NULL == ego_entry)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Ego not found: %s\n", ego_val);
-        resp = GNUNET_REST_create_json_response (NULL);
-        handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
-        cleanup_handle (handle);
-        return;
-      }
-    }
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego to issue token for: %s\n", egoname);
-  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST,
-                      strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST),
-                      &key);
-
-  //Token audience
-  audience = NULL;
-  if ( GNUNET_YES !=
-       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
-                                               &key) )
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Audience missing!\n");
-    resp = GNUNET_REST_create_json_response (NULL);
-    handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
-    cleanup_handle (handle);
-    return;
-  }
-  audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
-                                                &key);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Audience to issue token for: %s\n", audience);
-
-  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
-                                      &pub_key);
-  GNUNET_STRINGS_string_to_data (audience,
-                                 strlen (audience),
-                                 &aud_key,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  handle->token = GNUNET_IDENTITY_PROVIDER_token_create (&pub_key,
-                                                         aud_key);
-  GNUNET_free (aud_key);
-
-
-  //Get identity attributes
-  handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
-  handle->ego_entry = ego_entry;
-  handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
-                                                         priv_key,
-                                                         &attr_collect,
-                                                         handle);
-}
-
-
-/**
- * Build a GNUid token for identity
- * @param handle the handle
- * @param ego_entry the ego to build the token for
- * @param name name of the ego
- * @param token_aud token audience
- * @param token the resulting gnuid token
- * @return identifier string of token (label)
- */
-static void
-return_token_list (void *cls,
-                   const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  char* result_str;
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-
-  GNUNET_REST_jsonapi_data_serialize (handle->resp_object, &result_str);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
-  resp = GNUNET_REST_create_json_response (result_str);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_free (result_str);
-  cleanup_handle (handle);
-}
-
-/**
- * Collect all tokens for ego
- */
-static void
-token_collect (void *cls,
-               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-               const char *label,
-               unsigned int rd_count,
-               const struct GNUNET_GNSRECORD_Data *rd)
-{
-  int i;
-  char* data;
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_tmp;
-  struct JsonApiResource *json_resource;
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  json_t *issuer;
-  json_t *token;
-
-  if (NULL == label)
-  {
-    ego_tmp = handle->ego_head;
-    GNUNET_CONTAINER_DLL_remove (handle->ego_head,
-                                 handle->ego_tail,
-                                 ego_tmp);
-    GNUNET_free (ego_tmp->identifier);
-    GNUNET_free (ego_tmp->keystring);
-    GNUNET_free (ego_tmp);
-
-    if (NULL == handle->ego_head)
-    {
-      //Done
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token END\n");
-      handle->ns_it = NULL;
-      GNUNET_SCHEDULER_add_now (&return_token_list, handle);
-      return;
-    }
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Next ego: %s\n", handle->ego_head->identifier);
-    priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
-    handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
-                                                           priv_key,
-                                                           &token_collect,
-                                                           handle);
-    return;
-  }
-
-  for (i = 0; i < rd_count; i++)
-  {
-    if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
-    {
-      data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
-                                               rd[i].data,
-                                               rd[i].data_size);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token: %s\n", data);
-      json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
-                                                        label);
-      issuer = json_string (handle->ego_head->identifier);
-      GNUNET_REST_jsonapi_resource_add_attr (json_resource,
-                                             GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
-                                             issuer);
-      json_decref (issuer);
-      token = json_string (data);
-      GNUNET_REST_jsonapi_resource_add_attr (json_resource,
-                                             GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
-                                             token);
-      json_decref (token);
-
-      GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource);
-      GNUNET_free (data);
-    }
-  }
-
-  GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
-}
-
-
-
-/**
- * Respond to OPTIONS request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-list_token_cont (struct RestConnectionDataHandle *con_handle,
-                 const char* url,
-                 void *cls)
-{
-  char* ego_val;
-  struct GNUNET_HashCode key;
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct EgoEntry *ego_tmp;
-
-  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
-                      strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
-                      &key);
-
-  if ( GNUNET_YES ==
-       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
-                                               &key) )
-  {
-    ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
-                                                 &key);
-    //Remove non-matching egos
-    for (ego_entry = handle->ego_head;
-         NULL != ego_entry;)
-    {
-      ego_tmp = ego_entry;
-      ego_entry = ego_entry->next;
-      if (0 != strcmp (ego_val, ego_tmp->identifier))
-      {
-        GNUNET_CONTAINER_DLL_remove (handle->ego_head,
-                                     handle->ego_tail,
-                                     ego_tmp);
-        GNUNET_free (ego_tmp->identifier);
-        GNUNET_free (ego_tmp->keystring);
-        GNUNET_free (ego_tmp);
-      }
-    }
-  }
-  handle->resp_object = GNUNET_REST_jsonapi_object_new ();
-  if (NULL == handle->ego_head)
-  {
-    //Done
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No results.\n");
-    GNUNET_SCHEDULER_add_now (&return_token_list, handle);
-    return;
-  }
-  priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
-  handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
-  handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
-                                                         priv_key,
-                                                         &token_collect,
-                                                         handle);
-
-}
-
-
-
-
-static void
-process_lookup_result (void *cls, uint32_t rd_count,
-                       const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct RequestHandle *handle = cls;
-  json_t *root;
-  struct MHD_Response *resp;
-  char *result;
-  char* token_str;
-  char* record_str;
-
-  handle->lookup_request = NULL;
-  if (2 != rd_count)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Number of tokens %d != 2.",
-                rd_count);
-    handle->emsg = GNUNET_strdup ("Number of tokens != 2.");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  root = json_object();
-  record_str = 
-    GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN,
-                                      rd->data,
-                                      rd->data_size);
-
-  //Decrypt and parse
-  GNUNET_assert (GNUNET_OK ==  GNUNET_IDENTITY_PROVIDER_token_parse (record_str,
-                                                                     handle->priv_key,
-                                                                     &handle->token));
-
-  //Readable
-  GNUNET_assert (GNUNET_OK == GNUNET_IDENTITY_PROVIDER_token_to_string (handle->token,
-                                                                        handle->priv_key,
-                                                                        &token_str));
-
-  json_object_set_new (root, "access_token", json_string (token_str));
-  json_object_set_new (root, "token_type", json_string ("gnuid"));
-  GNUNET_free (token_str);
-  GNUNET_free (record_str);
-
-  result = json_dumps (root, JSON_INDENT(1));
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", result);
-  resp = GNUNET_REST_create_json_response (result);
-  GNUNET_free (result);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  cleanup_handle (handle);
-  json_decref (root);
-}
-
-
-static void
-exchange_token_ticket_cb (void *cls,
-                        struct GNUNET_IDENTITY_Ego *ego,
-                        void **ctx,
-                        const char *name)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_HashCode key;
-  char* code;
-  char* lookup_query;
-
-  handle->op = NULL;
-
-  if (NULL == ego)
-  {
-    handle->emsg = GNUNET_strdup ("No GNS identity found.");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_token_ticket,
-                      strlen (GNUNET_REST_JSONAPI_IDENTITY_token_ticket),
-                      &key);
-
-  if ( GNUNET_NO ==
-       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
-                                               &key) )
-  {
-    handle->emsg = GNUNET_strdup ("No code given.");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  code = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
-                                            &key);
-
-  handle->priv_key = GNUNET_IDENTITY_ego_get_private_key (ego);
-
-  if (GNUNET_SYSERR == GNUNET_IDENTITY_PROVIDER_ticket_parse (code,
-                                                              handle->priv_key,
-                                                              &handle->token_ticket))
-  {
-    handle->emsg = GNUNET_strdup ("Error extracting values from token code.");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Looking for token under %s\n",
-              handle->token_ticket->payload->label);
-  handle->gns_handle = GNUNET_GNS_connect (cfg);
-  GNUNET_asprintf (&lookup_query, "%s.gnu", handle->token_ticket->payload->label);
-  handle->lookup_request = GNUNET_GNS_lookup (handle->gns_handle,
-                                              lookup_query,
-                                              &handle->token_ticket->payload->identity_key,
-                                              GNUNET_GNSRECORD_TYPE_ID_TOKEN,
-                                              GNUNET_GNS_LO_LOCAL_MASTER,
-                                              NULL,
-                                              &process_lookup_result,
-                                              handle);
-  GNUNET_free (lookup_query);
-}
-
-/**
- * Respond to OAuth2 /token request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-exchange_token_ticket_cont (struct RestConnectionDataHandle *con_handle,
-                          const char* url,
-                          void *cls)
-{
-  struct RequestHandle *handle = cls;
-  char* grant_type;
-  struct GNUNET_HashCode key;
-
-  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_GRANT_TYPE,
-                      strlen (GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_GRANT_TYPE),
-                      &key);
-
-  if ( GNUNET_YES ==
-       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
-                                               &key) )
-  {
-    grant_type = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
-                                                    &key);
-  }
-
-  if (0 == strcmp ("authorization_code", grant_type)) {
-    //Get token from GNS
-    handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
-                                      "gns-master",
-                                      &exchange_token_ticket_cb,
-                                      handle);
-  }
-
-  //TODO fail here
-}
-
-/**
- * Respond to OPTIONS request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-options_cont (struct RestConnectionDataHandle *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_json_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)
-{
-  static const struct GNUNET_REST_RestConnectionHandler handlers[] = {
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE, &issue_token_cont},
-    //{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK, &check_token_cont},
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN, &list_token_cont},
-    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_TOKEN, &options_cont},
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN, &exchange_token_ticket_cont},
-    GNUNET_REST_HANDLER_END
-  };
-
-  if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, handlers, handle))
-  {
-    handle->emsg = GNUNET_strdup ("Request unsupported");
-    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;
-    GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
-    GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
-  }
-
-}
-
-/**
- * Function processing the REST call
- *
- * @param method HTTP method
- * @param url URL of the HTTP request
- * @param data body of the HTTP request (optional)
- * @param data_size length of the body
- * @param proc callback function for the result
- * @param proc_cls closure for callback function
- * @return GNUNET_OK if request accepted
- */
-static void
-rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle,
-                              GNUNET_REST_ResultProcessor proc,
-                              void *proc_cls)
-{
-  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
-  struct GNUNET_HashCode key;
-  char* attr_list;
-  char* attr_list_tmp;
-  char* attr;
-
-  GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_ATTR_LIST,
-                      strlen (GNUNET_IDENTITY_TOKEN_ATTR_LIST),
-                      &key);
-
-  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
-
-  handle->proc_cls = proc_cls;
-  handle->proc = proc;
-  handle->state = ID_REST_STATE_INIT;
-  handle->conndata_handle = conndata_handle;
-  handle->data = conndata_handle->data;
-  handle->data_size = conndata_handle->data_size;
-  handle->method = conndata_handle->method;
-  if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
-                                                            &key))
-  {
-    handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
-                                                             GNUNET_NO);
-    attr_list = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
-                                                   &key);
-    if (NULL != attr_list)
-    {
-      attr_list_tmp = GNUNET_strdup (attr_list);
-      attr = strtok(attr_list_tmp, ",");
-      for (; NULL != attr; attr = strtok (NULL, ","))
-      {
-        GNUNET_CRYPTO_hash (attr,
-                            strlen (attr),
-                            &key);
-        GNUNET_CONTAINER_multihashmap_put (handle->attr_map,
-                                           &key,
-                                           attr,
-                                           GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
-      }
-      GNUNET_free (attr_list_tmp);
-    }
-  }
-
-
-  GNUNET_asprintf (&handle->url, "%s", conndata_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->timeout_task =
-    GNUNET_SCHEDULER_add_delayed (handle->timeout,
-                                  &do_error,
-                                  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_token_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_TOKEN;
-  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_INFO,
-              _("Identity Token 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_token_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 Token REST plugin is finished\n");
-  return NULL;
-}
-
-/* end of plugin_rest_gns.c */
index a23629b41fd9c28f49c52c66469f33fef4857e88..fd689490a086cb67e97dd09b74d5b838e8295d13 100644 (file)
@@ -44,11 +44,31 @@ value_to_string (void *cls,
                  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:
     case GNUNET_GNSRECORD_TYPE_ID_TOKEN:
       return GNUNET_strndup (data, data_size);
+    case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA:
+        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);
+        return result;
+
     default:
       return NULL;
   }
@@ -73,6 +93,12 @@ string_to_value (void *cls,
                  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)
@@ -82,6 +108,46 @@ string_to_value (void *cls,
       *data = GNUNET_strdup (s);
       *data_size = strlen (s);
       return GNUNET_OK;
+    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);
+      memcpy (write_ptr, str, strlen (str) + 1); //with 0-Terminator
+      GNUNET_free (tmp_tok);
+      return GNUNET_OK;
+
     default:
       return GNUNET_SYSERR;
   }
@@ -92,14 +158,15 @@ string_to_value (void *cls,
  * 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 },
-  { NULL, UINT32_MAX }
-};
+        static struct {
+          const char *name;
+          uint32_t number;
+        } name_map[] = {
+          { "ID_ATTR", GNUNET_GNSRECORD_TYPE_ID_ATTR },
+          { "ID_TOKEN", GNUNET_GNSRECORD_TYPE_ID_TOKEN },
+          { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA },
+          { NULL, UINT32_MAX }
+        };
 
 
 /**
diff --git a/src/include/gnunet_identity_provider_lib.h b/src/include/gnunet_identity_provider_lib.h
new file mode 100644 (file)
index 0000000..6e41a00
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 Christian Grothoff (and other contributing authors)
+
+   GNUnet is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNUnet; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @file include/gnunet_identity_provider_lib.h
+ * @brief GNUnet Identity Provider library
+ *
+ */
+#ifndef GNUNET_IDENTITY_PROVIDER_LIB_H
+#define GNUNET_IDENTITY_PROVIDER_LIB_H
+
+#include "gnunet_crypto_lib.h"
+#include <jansson.h>
+
+struct GNUNET_IDENTITY_PROVIDER_Token
+{
+  /**
+   * JSON header
+   */
+  json_t *header;
+
+  /**
+   * JSON Payload
+   */
+  json_t *payload;
+
+  /**
+   * Token Signature
+   */
+  struct GNUNET_CRYPTO_EcdsaSignature signature;
+  
+  /**
+   * Audience Pubkey
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
+};
+
+struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload
+{
+  /**
+   * Nonce
+   */
+  char* nonce;
+
+  /**
+   * Label
+   */
+  char *label;
+
+  /**
+   * Issuing Identity
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity_key;
+};
+
+
+struct GNUNET_IDENTITY_PROVIDER_TokenTicket
+{
+  /**
+   * Meta info
+   */
+  struct GNUNET_IDENTITY_PROVIDER_TokenTicketPayload *payload;
+
+  /**
+   * ECDH Pubkey
+   */
+  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
+
+  /**
+   * Signature
+   */
+  struct GNUNET_CRYPTO_EcdsaSignature signature;
+
+  /**
+   * Target identity
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
+};
+
+
+
+/**
+ * Create an identity token
+ *
+ * @param iss the issuer string for the token
+ * @param aud the audience of the token
+ *
+ * @return a new token
+ */
+struct GNUNET_IDENTITY_PROVIDER_Token*
+GNUNET_IDENTITY_PROVIDER_token_create (const struct GNUNET_CRYPTO_EcdsaPublicKey *iss,
+                                       const struct GNUNET_CRYPTO_EcdsaPublicKey* aud);
+
+/**
+ * Destroy an identity token
+ *
+ * @param token the token to destroy
+ */
+void
+GNUNET_IDENTITY_PROVIDER_token_destroy (struct GNUNET_IDENTITY_PROVIDER_Token *token);
+
+/**
+ * Add a new key value pair to the token
+ * 
+ * @param token the token to modify
+ * @param key the key
+ * @param value the value
+ */
+void
+GNUNET_IDENTITY_PROVIDER_token_add_attr (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
+                                         const char* key,
+                                         const char* value);
+
+/**
+ * Add a new key value pair to the token with the value as json
+ *
+ * @param the token to modify
+ * @param key the key
+ * @param value the value
+ *
+ */
+void
+GNUNET_IDENTITY_PROVIDER_token_add_json (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
+                         const char* key,
+                         json_t* value);
+
+/**
+ * Serialize a token. The token will be signed and base64 according to the
+ * JWT format. The signature is base32-encoded ECDSA.
+ * The resulting JWT is encrypted using 
+ * ECDHE for the audience and Base64
+ * encoded in result. The audience requires the ECDHE public key P 
+ * to decrypt the token T. The key P is included in the result and prepended
+ * before the token
+ *
+ * @param token the token to serialize
+ * @param priv_key the private key used to sign the token
+ * @param ecdhe_privkey the ECDHE private key used to encrypt the token
+ * @param result P,Base64(E(T))
+ *
+ * @return GNUNET_OK on success
+ */
+int 
+GNUNET_IDENTITY_PROVIDER_token_serialize (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
+                          const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                          struct GNUNET_CRYPTO_EcdhePrivateKey **ecdhe_privkey,
+                          char **result);
+
+/**
+ * Parses the serialized token and returns a token
+ *
+ * @param data the serialized token
+ * @param priv_key the private key of the audience
+ * @param result the token
+ *
+ * @return GNUNET_OK on success
+ */
+int
+GNUNET_IDENTITY_PROVIDER_token_parse (const char* data,
+                      const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                      struct GNUNET_IDENTITY_PROVIDER_Token **result);
+
+/**
+ * Parses the serialized token and returns a token
+ * This variant is intended for the party that issued the token and also
+ * wants to decrypt the serialized token.
+ *
+ * @param data the serialized token
+ * @param priv_key the private (!) ECDHE key
+ * @param aud_key the identity of the audience
+ * @param result the token
+ *
+ * @return GNUNET_OK on success
+ */
+int
+GNUNET_IDENTITY_PROVIDER_token_parse2 (const char* data,
+                       const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
+                       const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                       struct GNUNET_IDENTITY_PROVIDER_Token **result);
+
+
+/**
+ *
+ * Returns a JWT-string representation of the token
+ *
+ * @param token the token
+ * @param priv_key the private key used to sign the JWT
+ * @param result the JWT
+ *
+ * @return GNUNET_OK on success
+ */
+int
+GNUNET_IDENTITY_PROVIDER_token_to_string (const struct GNUNET_IDENTITY_PROVIDER_Token *token,
+                          const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                          char **result);
+
+/**
+ *
+ * Creates a ticket that can be exchanged by the audience for 
+ * the token. The token must be placed under the label
+ *
+ * @param nonce_str nonce provided by the audience that requested the ticket
+ * @param iss_pkey the issuer pubkey used to sign the ticket
+ * @param label the label encoded in the ticket
+ * @param aud_ley the audience pubkey used to encrypt the ticket payload
+ *
+ * @return the ticket
+ */
+struct GNUNET_IDENTITY_PROVIDER_TokenTicket*
+GNUNET_IDENTITY_PROVIDER_ticket_create (const char* nonce_str,
+                            const struct GNUNET_CRYPTO_EcdsaPublicKey* iss_pkey,
+                            const char* lbl_str,
+                            const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key);
+
+/**
+ * Serialize a ticket. Returns the Base64 representation of the ticket.
+ * Format: Base64( { payload: E(Payload), ecdhe: K, signature: signature } )
+ *
+ * @param ticket the ticket to serialize
+ * @param priv_key the issuer private key to sign the ticket payload
+ * @param result the serialized ticket
+ *
+ * @return GNUNET_OK on success
+ */
+int
+GNUNET_IDENTITY_PROVIDER_ticket_serialize (struct GNUNET_IDENTITY_PROVIDER_TokenTicket *ticket,
+                               const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                               char **result);
+
+/**
+ * Destroys a ticket
+ *
+ * @param the ticket to destroy
+ */
+void
+GNUNET_IDENTITY_PROVIDER_ticket_destroy (struct GNUNET_IDENTITY_PROVIDER_TokenTicket *ticket);
+
+/**
+ * Parses a serialized ticket
+ *
+ * @param data the serialized ticket
+ * @param priv_key the audience private key
+ * @param ticket the ticket
+ *
+ * @return GNUNET_OK on success
+ */
+int
+GNUNET_IDENTITY_PROVIDER_ticket_parse (const char* raw_data,
+                           const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                           struct GNUNET_IDENTITY_PROVIDER_TokenTicket **ticket);
+
+#endif
index dd6afbec5975cca3e6d686c91ace8e44a9e158dd..95d570b546191f4d0f85a16cfe6985256736e5c2 100644 (file)
@@ -182,9 +182,9 @@ extern "C"
 #define GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN 26
 
 /**
- * Signature for a GNUid Token Reference
+ * Signature for a GNUid Ticket
  */
-#define GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN_CODE 27
+#define GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET 27
 
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
index ba18c5dfa99862b83b2634c77591803e3e534c17..0e7213b64dc32714eb0d81c03ca2436a2ce9c0a9 100644 (file)
@@ -464,15 +464,8 @@ schedule_httpd ()
   }
   if (NULL != httpd_task)
     GNUNET_SCHEDULER_cancel (httpd_task);
-  if ( (MHD_YES != haveto) &&
-       (-1 == max))
-  {
-    /* daemon is idle, kill after timeout */
-    httpd_task = GNUNET_SCHEDULER_add_delayed (MHD_CACHE_TIMEOUT,
-                                               &kill_httpd_task,
-                                               NULL);
-  }
-  else
+  if ( (MHD_YES == haveto) ||
+       (-1 != max))
   {
     httpd_task =
       GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,