gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r36796 - in gnunet/src: identity-provider include


From: gnunet
Subject: [GNUnet-SVN] r36796 - in gnunet/src: identity-provider include
Date: Fri, 8 Jan 2016 19:59:47 +0100

Author: schanzen
Date: 2016-01-08 19:59:47 +0100 (Fri, 08 Jan 2016)
New Revision: 36796

Added:
   gnunet/src/identity-provider/gnunet-service-identity-provider.c
   gnunet/src/identity-provider/identity_provider.h
   gnunet/src/identity-provider/identity_provider_api.c
   gnunet/src/identity-provider/identity_token.c
   gnunet/src/identity-provider/identity_token.h
   gnunet/src/include/gnunet_identity_provider_service.h
Removed:
   gnunet/src/identity-provider/gnunet-service-identity-token.c
   gnunet/src/identity-provider/identity-token.c
   gnunet/src/include/gnunet_identity_provider_lib.h
Modified:
   gnunet/src/identity-provider/Makefile.am
   gnunet/src/identity-provider/plugin_rest_identity_token.c
   gnunet/src/include/gnunet_protocols.h
Log:
- More heavy refactoring. Probably lots of broken things to see here.



Modified: gnunet/src/identity-provider/Makefile.am
===================================================================
--- gnunet/src/identity-provider/Makefile.am    2016-01-07 21:10:24 UTC (rev 
36795)
+++ gnunet/src/identity-provider/Makefile.am    2016-01-08 18:59:47 UTC (rev 
36796)
@@ -21,32 +21,25 @@
 
 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-provider
 
-gnunet_service_identity_token_SOURCES = \
- gnunet-service-identity-token.c
-gnunet_service_identity_token_LDADD = \
- libgnunetidentityprovider.la \
+gnunet_service_identity_provider_SOURCES = \
+ gnunet-service-identity-provider.c \
+ identity_token.c
+gnunet_service_identity_provider_LDADD = \
  $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
  $(top_builddir)/src/util/libgnunetutil.la \
  $(top_builddir)/src/namestore/libgnunetnamestore.la \
  $(top_builddir)/src/identity/libgnunetidentity.la \
+ $(top_builddir)/src/gns/libgnunetgns.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 = \
@@ -53,7 +46,6 @@
        $(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 = \

Copied: gnunet/src/identity-provider/gnunet-service-identity-provider.c (from 
rev 36795, gnunet/src/identity-provider/gnunet-service-identity-token.c)
===================================================================
--- gnunet/src/identity-provider/gnunet-service-identity-provider.c             
                (rev 0)
+++ gnunet/src/identity-provider/gnunet-service-identity-provider.c     
2016-01-08 18:59:47 UTC (rev 36796)
@@ -0,0 +1,1328 @@
+/*
+   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/identity/gnunet-service-identity-provider.c
+ * @brief Identity Token Service
+ *
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_protocols.h"
+#include "gnunet_identity_service.h"
+#include "gnunet_gnsrecord_lib.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_gns_service.h"
+#include <jansson.h>
+#include "gnunet_signatures.h"
+#include "identity_provider.h"
+#include "identity_token.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;
+
+/**
+ * GNS handle
+ */
+static struct GNUNET_GNS_Handle *gns_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 IdentityToken *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;
+
+/**
+ * Handle to the statistics service.
+ */
+static struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Notification context, simplifies client broadcasts.
+ */
+static struct GNUNET_SERVER_NotificationContext *nc;
+
+struct ExchangeHandle
+{
+
+  /**
+   * Client connection
+   */
+  struct GNUNET_SERVER_Client *client;
+
+  /**
+   * Ticket
+   */
+  struct TokenTicket *ticket;
+
+  /**
+   * Token returned
+   */
+  struct IdentityToken *token;
+
+  /**
+   * LookupRequest
+   */
+  struct GNUNET_GNS_LookupRequest *lookup_request;
+  
+  /**
+   * Audience Key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey;
+
+  /**
+   * Label to return
+   */
+  char *label;
+};
+
+struct IssueHandle
+{
+
+  /**
+   * Client connection
+   */
+  struct GNUNET_SERVER_Client *client;
+
+  /**
+   * Issuer Key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key;
+
+  /**
+   * Issue pubkey
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey iss_pkey;
+
+  /**
+   * Audience Key
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
+
+  /**
+   * Expiration
+   */
+  struct GNUNET_TIME_Absolute expiration;
+
+  /**
+   * Scopes
+   */
+  char *scopes;
+
+  /**
+   * nonce
+   */
+  uint64_t nonce;
+
+  /**
+   * NS iterator
+   */
+  struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+
+  /**
+   * Attribute map
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *attr_map;
+
+  /**
+   * Token
+   */
+  struct IdentityToken *token;
+
+  /**
+   * Ticket
+   */
+  struct TokenTicket *ticket;
+
+  /**
+   * QueueEntry
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+};
+
+/**
+ * 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 IdentityToken *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 = 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"))
+    {
+      token_add_json (new_token, key, json_integer (new_exp.abs_value_us));
+    }
+    else if (0 == strcmp (key, "nbf"))
+    {
+      token_add_json (new_token, key, json_integer (new_nbf.abs_value_us));
+    }
+    else if (0 == strcmp (key, "iat"))
+    {
+      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")))
+    {
+      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);
+        token_add_json (new_token, key, cur_value);
+      }
+    }
+  }
+
+  // reassemble and set
+  GNUNET_assert (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);
+  token_destroy (new_token);
+  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));
+
+  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 != nc)
+  {
+    GNUNET_SERVER_notification_context_destroy (nc);
+    nc = NULL;
+  }
+  if (NULL != stats)
+  {
+    GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
+    stats = NULL;
+  }
+
+  if (NULL != timeout_task)
+    GNUNET_SCHEDULER_cancel (timeout_task);
+  if (NULL != update_task)
+    GNUNET_SCHEDULER_cancel (update_task);
+  if (NULL != identity_handle)
+    GNUNET_IDENTITY_disconnect (identity_handle);
+  if (NULL != gns_handle)
+    GNUNET_GNS_disconnect (gns_handle);
+  if (NULL != 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();
+}
+
+
+static struct GNUNET_IDENTITY_PROVIDER_ExchangeResultMessage*
+create_exchange_result_message (const char* token,
+                                const char* label)
+{
+  struct GNUNET_IDENTITY_PROVIDER_ExchangeResultMessage *erm;
+  uint16_t token_len = strlen (token) + 1;
+  erm = GNUNET_malloc (sizeof (struct 
GNUNET_IDENTITY_PROVIDER_ExchangeResultMessage) 
+                       + token_len);
+  erm->header.type = htons 
(GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT);
+  erm->header.size = htons (sizeof (struct 
GNUNET_IDENTITY_PROVIDER_ExchangeResultMessage) 
+                            + token_len);
+  memcpy (&erm[1], token, token_len);
+  return erm;
+}
+
+
+static struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage*
+create_issue_result_message (const char* ticket)
+{
+  struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage *irm;
+
+  irm = GNUNET_malloc (sizeof (struct 
GNUNET_IDENTITY_PROVIDER_IssueResultMessage) + strlen(ticket) + 1);
+  irm->header.type = htons 
(GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT);
+  irm->header.size = htons (sizeof (struct 
GNUNET_IDENTITY_PROVIDER_IssueResultMessage) + strlen (ticket) + 1);
+  memcpy (&irm[1], ticket, strlen (ticket) + 1);
+  return irm;
+}
+
+void
+store_token_issue_cont (void *cls,
+                        int32_t success,
+                        const char *emsg)
+{
+  struct IssueHandle *handle = cls;
+  struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage *irm;
+  char* token_ticket_str;
+  handle->ns_qe = NULL;
+  if (GNUNET_SYSERR == success)
+  {
+    //TODO err msg
+    return;
+  }
+  if (GNUNET_OK != ticket_serialize (handle->ticket,
+                                     &handle->iss_key,
+                                     &token_ticket_str))
+  {
+    GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map);
+    ticket_destroy (handle->ticket);
+    GNUNET_free (handle);
+    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 
+    return;
+  }
+  irm = create_issue_result_message (token_ticket_str);
+  GNUNET_SERVER_notification_context_unicast (nc,
+                                              handle->client,
+                                              &irm->header,
+                                              GNUNET_NO);
+  GNUNET_free (irm);
+  GNUNET_free (token_ticket_str);
+  GNUNET_SERVER_receive_done (handle->client, GNUNET_OK);
+}
+
+/**
+ * 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 IssueHandle *handle = cls;
+  struct GNUNET_GNSRECORD_Data token_record[2];
+  struct GNUNET_TIME_Relative etime_rel;
+  char *lbl_str;
+  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_asprintf (&nonce_str, "%d", handle->nonce);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str);
+
+  //Label
+  rnd_key = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, 
UINT64_MAX);
+  GNUNET_STRINGS_base64_encode ((char*)&rnd_key, sizeof (uint64_t), &lbl_str);
+  GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key,
+                                      &pub_key);
+
+  handle->ticket = ticket_create (nonce_str,
+                                  &pub_key,
+                                  lbl_str,
+                                  &aud_pkey);
+
+
+
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_fancy_time_to_relative ("1d", //TODO
+                                             &etime_rel))
+  {
+    ticket_destroy (handle->ticket);
+    GNUNET_free (handle);
+    GNUNET_SCHEDULER_add_now (&do_shutdown, handle);
+    return;
+  }
+  time = GNUNET_TIME_absolute_get().abs_value_us;
+  exp_time = time + etime_rel.rel_value_us;
+
+  token_add_json (handle->token, "nbf", json_integer (time));
+  token_add_json (handle->token, "iat", json_integer (time));
+  token_add_json (handle->token, "exp", json_integer (exp_time));
+  token_add_attr (handle->token, "nonce", nonce_str);
+
+
+  //Token in a serialized encrypted format 
+  GNUNET_assert (token_serialize (handle->token,
+                                  &handle->iss_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;
+
+
+  token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
+    + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
+    + strlen (handle->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, &handle->aud_key, 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 (ns_handle,
+                                                  priv_key,
+                                                  lbl_str,
+                                                  2,
+                                                  token_record,
+                                                  &store_token_issue_cont,
+                                                  handle);
+  GNUNET_free (lbl_str);
+  GNUNET_free (enc_token_str);
+}
+
+/**
+ * Collect attributes for token
+ */
+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 IssueHandle *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);
+      token_add_json (handle->token,
+                      label,
+                      json_string (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))
+  {
+    token_add_json (handle->token, label, attr_arr);
+  }
+  json_decref (attr_arr);
+  GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+}
+
+static void
+process_lookup_result (void *cls, uint32_t rd_count,
+                       const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct ExchangeHandle *handle = cls;
+  struct GNUNET_IDENTITY_PROVIDER_ExchangeResultMessage *erm;
+  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);
+    GNUNET_free (handle->label);
+    GNUNET_free (handle);
+    GNUNET_SCHEDULER_add_now (&do_shutdown, handle);
+    return;
+  }
+
+  record_str = 
+    GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN,
+                                      rd->data,
+                                      rd->data_size);
+
+  //Decrypt and parse
+  GNUNET_assert (GNUNET_OK ==  token_parse (record_str,
+                                            &handle->aud_privkey,
+                                            &handle->token));
+
+  //Readable
+  GNUNET_assert (GNUNET_OK == token_to_string (handle->token,
+                                               &handle->aud_privkey,
+                                               &token_str));
+
+  erm = create_exchange_result_message (token_str,
+                                        handle->label);
+  GNUNET_SERVER_notification_context_unicast (nc,
+                                              handle->client,
+                                              &erm->header,
+                                              GNUNET_NO);
+  GNUNET_free (erm);
+  GNUNET_SERVER_receive_done (handle->client, GNUNET_OK);
+
+}
+
+/**
+ *
+ * Handler for exchange message
+ *
+ * @param cls unused
+ * @param client who sent the message
+ * @param message the message
+ */
+static void
+handle_exchange_message (void *cls,
+                         struct GNUNET_SERVER_Client *client,
+                         const struct GNUNET_MessageHeader *message)
+{
+  const struct GNUNET_IDENTITY_PROVIDER_ExchangeMessage *em;
+  struct ExchangeHandle *xchange_handle;
+  uint16_t size;
+  const char *ticket;
+  char *lookup_query;
+
+  size = ntohs (message->size);
+  if (size <= sizeof (struct GNUNET_IDENTITY_PROVIDER_ExchangeMessage))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  em = (const struct GNUNET_IDENTITY_PROVIDER_ExchangeMessage *) message;
+  ticket = (const char *) &em[1];
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received EXCHANGE of `%s' from client\n",
+              ticket);
+  xchange_handle = GNUNET_malloc (sizeof (struct ExchangeHandle));
+  xchange_handle->aud_privkey = em->aud_privkey;
+  if (GNUNET_SYSERR == ticket_parse (ticket,
+                                     &xchange_handle->aud_privkey,
+                                     &xchange_handle->ticket))
+  {
+    GNUNET_free (xchange_handle);
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Looking for token under %s\n",
+              xchange_handle->ticket->payload->label);
+  GNUNET_asprintf (&lookup_query,
+                   "%s.gnu",
+                   xchange_handle->ticket->payload->label);
+  xchange_handle->lookup_request = GNUNET_GNS_lookup (gns_handle,
+                                                      lookup_query,
+                                                      
&xchange_handle->ticket->payload->identity_key,
+                                                      
GNUNET_GNSRECORD_TYPE_ID_TOKEN,
+                                                      
GNUNET_GNS_LO_LOCAL_MASTER,
+                                                      NULL,
+                                                      &process_lookup_result,
+                                                      xchange_handle);
+  GNUNET_free (lookup_query);
+
+}
+
+/**
+ *
+ * Handler for issue message
+ *
+ * @param cls unused
+ * @param client who sent the message
+ * @param message the message
+ */
+static void
+handle_issue_message (void *cls,
+                      struct GNUNET_SERVER_Client *client,
+                      const struct GNUNET_MessageHeader *message)
+{
+  const struct GNUNET_IDENTITY_PROVIDER_IssueMessage *im;
+  uint16_t size;
+  const char *scopes;
+  char *scopes_tmp;
+  char *scope;
+  char *attr_list_tmp;
+  struct GNUNET_HashCode key;
+  struct IssueHandle *issue_handle;
+
+  size = ntohs (message->size);
+  if (size <= sizeof (struct GNUNET_IDENTITY_PROVIDER_IssueMessage))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  im = (const struct GNUNET_IDENTITY_PROVIDER_IssueMessage *) message;
+  scopes = (const char *) &im[1];
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received ISSUE of `%s' from client\n",
+              scope);
+  issue_handle = GNUNET_malloc (sizeof (struct IssueHandle));
+  issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
+                                                                 GNUNET_NO);
+  scopes_tmp = GNUNET_strdup (scopes);
+  scope = strtok(attr_list_tmp, ",");
+  for (; NULL != scope; scope = strtok (NULL, ","))
+  {
+    GNUNET_CRYPTO_hash (scope,
+                        strlen (scope),
+                        &key);
+    GNUNET_CONTAINER_multihashmap_put (issue_handle->attr_map,
+                                       &key,
+                                       scope,
+                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+  }
+  GNUNET_free (scopes_tmp);
+
+  issue_handle->aud_key = im->aud_key;
+  issue_handle->iss_key = im->iss_key;
+  issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration);
+  issue_handle->nonce = im->nonce;
+  GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key,
+                                      &issue_handle->iss_pkey);
+  issue_handle->token = token_create (&issue_handle->iss_pkey,
+                                      &im->aud_key);
+
+  issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
+                                                               &im->iss_key,
+                                                               &attr_collect,
+                                                               issue_handle);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK); //TODO here?
+
+
+}
+
+/**
+ * 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, 
+     struct GNUNET_SERVER_Handle *server,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
+    {&handle_issue_message, NULL,
+      GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE, 0},
+    {&handle_exchange_message, NULL,
+      GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE, 0},
+    {NULL, NULL, 0, 0}
+  };
+
+  cfg = c;
+
+  stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
+  GNUNET_SERVER_add_handlers (server, handlers);
+  nc = GNUNET_SERVER_notification_context_create (server, 1);
+
+  //Connect to identity and namestore services
+  ns_handle = GNUNET_NAMESTORE_connect (cfg);
+  if (NULL == ns_handle)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to 
namestore");
+  }
+
+  gns_handle = GNUNET_GNS_connect (cfg);
+  if (NULL == gns_handle)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
+  }
+
+  identity_handle = GNUNET_IDENTITY_connect (cfg,
+                                             &list_ego,
+                                             NULL);
+
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                &do_shutdown, NULL);
+}
+
+
+/**
+ *
+ * The main function
+ *
+ * @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)
+{
+  return  (GNUNET_OK ==
+           GNUNET_SERVICE_run (argc, argv, "identity-provider",
+                               GNUNET_SERVICE_OPTION_NONE,
+                               &run, NULL)) ? 0 : 1;
+}
+
+/* end of gnunet-rest-server.c */

Deleted: gnunet/src/identity-provider/gnunet-service-identity-token.c
===================================================================
--- gnunet/src/identity-provider/gnunet-service-identity-token.c        
2016-01-07 21:10:24 UTC (rev 36795)
+++ gnunet/src/identity-provider/gnunet-service-identity-token.c        
2016-01-08 18:59:47 UTC (rev 36796)
@@ -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 */

Deleted: gnunet/src/identity-provider/identity-token.c
===================================================================
--- gnunet/src/identity-provider/identity-token.c       2016-01-07 21:10:24 UTC 
(rev 36795)
+++ gnunet/src/identity-provider/identity-token.c       2016-01-08 18:59:47 UTC 
(rev 36796)
@@ -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 */

Added: gnunet/src/identity-provider/identity_provider.h
===================================================================
--- gnunet/src/identity-provider/identity_provider.h                            
(rev 0)
+++ gnunet/src/identity-provider/identity_provider.h    2016-01-08 18:59:47 UTC 
(rev 36796)
@@ -0,0 +1,164 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2016 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 Liceidentity 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 Liceidentity for more details.
+
+     You should have received a copy of the GNU General Public Liceidentity
+     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-provider/identity_provider.h
+ *
+ * @brief Common type definitions for the identity provider
+ *        service and API.
+ */
+#ifndef IDENTITY_PROVIDER_H
+#define IDENTITY_PROVIDER_H
+
+#include "gnunet_common.h"
+
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * The token
+ */
+struct GNUNET_IDENTITY_PROVIDER_Token
+{
+  /**
+   * The JWT representation of the identity token
+   */
+  char *data;
+};
+
+/**
+ * The ticket
+ */
+struct GNUNET_IDENTITY_PROVIDER_Ticket
+{
+  /**
+   * The Base64 representation of the ticket
+   */
+  char *data;
+};
+
+/**
+ * Answer from service to client after issue operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE
+   */
+  struct GNUNET_MessageHeader header;
+
+  /* followed by 0-terminated ticket */
+
+};
+
+
+/**
+ * Ticket exchange message.
+ */
+struct GNUNET_IDENTITY_PROVIDER_ExchangeResultMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Number of bytes in token string including 0-termination, in NBO;
+   * 0 on error.
+   */
+  uint16_t name_len GNUNET_PACKED;
+
+  /* followed by 0-terminated token */
+
+};
+
+
+
+/**
+ * Client requests IdP to issue token.
+ */
+struct GNUNET_IDENTITY_PROVIDER_IssueMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Issuer identity private key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key;
+
+  /**
+   * Audience public key
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
+
+  /**
+   * Nonce
+   */
+  uint64_t nonce;
+
+  /**
+   * Expiration of token in NBO.
+   */
+  struct GNUNET_TIME_AbsoluteNBO expiration;
+
+
+  /* followed by 0-terminated comma-separated scope list */
+
+};
+
+
+/**
+ * Use to exchange a ticket for a token
+ */
+struct GNUNET_IDENTITY_PROVIDER_ExchangeMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT
+   */
+  struct GNUNET_MessageHeader header;
+  
+  /**
+   * Audience identity private key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey;
+
+
+  /**
+   * Number of bytes in ticket string including 0-termination, in NBO.
+   */
+  uint16_t name_len GNUNET_PACKED;
+
+  /**
+   * Always zero.
+   */
+  uint16_t reserved GNUNET_PACKED;
+
+  /* followed by 0-terminated ticket string */
+
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif

Added: gnunet/src/identity-provider/identity_provider_api.c
===================================================================
--- gnunet/src/identity-provider/identity_provider_api.c                        
        (rev 0)
+++ gnunet/src/identity-provider/identity_provider_api.c        2016-01-08 
18:59:47 UTC (rev 36796)
@@ -0,0 +1,611 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2016 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 Liceidentity 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 Liceidentity for more details.
+
+     You should have received a copy of the GNU General Public Liceidentity
+     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-provider/identity_provider_api.c
+ * @brief api to interact with the identity provider service
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_protocols.h"
+#include "gnunet_identity_provider_service.h"
+#include "identity_provider.h"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__)
+
+
+
+/**
+ * Handle for an operation with the service.
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation
+{
+
+  /**
+   * Main handle.
+   */
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h;
+
+  /**
+   * We keep operations in a DLL.
+   */
+  struct GNUNET_IDENTITY_PROVIDER_Operation *next;
+
+  /**
+   * We keep operations in a DLL.
+   */
+  struct GNUNET_IDENTITY_PROVIDER_Operation *prev;
+
+  /**
+   * Message to send to the service.
+   * Allocated at the end of this struct.
+   */
+  const struct GNUNET_MessageHeader *msg;
+
+  /**
+   * Continuation to invoke with the result of the transmission; @e cb
+   * will be NULL in this case.
+   */
+  GNUNET_IDENTITY_PROVIDER_ExchangeCallback ex_cb;
+
+  /**
+   * Continuation to invoke with the result of the transmission for
+   * 'issue' operations (@e cont will be NULL in this case).
+   */
+  GNUNET_IDENTITY_PROVIDER_IssueCallback iss_cb;
+
+  /**
+   * Closure for @e cont or @e cb.
+   */
+  void *cls;
+
+};
+
+
+/**
+ * Handle for the service.
+ */
+struct GNUNET_IDENTITY_PROVIDER_Handle
+{
+  /**
+   * Configuration to use.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Socket (if available).
+   */
+  struct GNUNET_CLIENT_Connection *client;
+
+  /**
+   * Function to call when we receive updates.
+   */
+  GNUNET_IDENTITY_PROVIDER_Callback cb;
+
+  /**
+   * Closure for 'cb'.
+   */
+  void *cb_cls;
+
+  /**
+   * Head of active operations.
+   */
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op_head;
+
+  /**
+   * Tail of active operations.
+   */
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail;
+
+  /**
+   * Currently pending transmission request, or NULL for none.
+   */
+  struct GNUNET_CLIENT_TransmitHandle *th;
+
+  /**
+   * Task doing exponential back-off trying to reconnect.
+   */
+  struct GNUNET_SCHEDULER_Task * reconnect_task;
+
+  /**
+   * Time for next connect retry.
+   */
+  struct GNUNET_TIME_Relative reconnect_delay;
+
+  /**
+   * Are we polling for incoming messages right now?
+   */
+  int in_receive;
+
+};
+
+
+/**
+ * Try again to connect to the service.
+ *
+ * @param cls handle to the service.
+ * @param tc scheduler context
+ */
+static void
+reconnect (void *cls,
+          const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Reschedule a connect attempt to the service.
+ *
+ * @param h transport service to reconnect
+ */
+static void
+reschedule_connect (struct GNUNET_IDENTITY_Handle *h)
+{
+  GNUNET_assert (h->reconnect_task == NULL);
+
+  if (NULL != h->th)
+  {
+    GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
+    h->th = NULL;
+  }
+  if (NULL != h->client)
+  {
+    GNUNET_CLIENT_disconnect (h->client);
+    h->client = NULL;
+  }
+  h->in_receive = GNUNET_NO;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Scheduling task to reconnect to identity provider service in %s.\n",
+       GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay, 
GNUNET_YES));
+  h->reconnect_task =
+      GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h);
+  h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
+}
+
+
+/**
+ * Type of a function to call when we receive a message
+ * from the service.
+ *
+ * @param cls closure
+ * @param msg message received, NULL on timeout or fatal error
+ */
+static void
+message_handler (void *cls,
+                const struct GNUNET_MessageHeader *msg)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+  struct GNUNET_IDENTITY_PROVIDER_Token token;
+  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
+  const struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage *irm;
+  const struct GNUNET_IDENTITY_ExchangeResultMessage *erm;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pub;
+  struct GNUNET_HashCode id;
+  const char *str;
+  uint16_t size;
+  uint16_t name_len;
+
+  if (NULL == msg)
+  {
+    reschedule_connect (h);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received message of type %d from identity provider service\n",
+       ntohs (msg->type));
+  size = ntohs (msg->size);
+  switch (ntohs (msg->type))
+  {
+  case GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT:
+    if (size < sizeof (struct GNUNET_IDENTITY_IssueResultMessage))
+    {
+      GNUNET_break (0);
+      reschedule_connect (h);
+      return;
+    }
+    irm = (const struct GNUNET_IDENTITY_IssueResultMessage *) msg;
+    str = (const char *) &irm[1];
+    if ( (size > sizeof (struct GNUNET_IDENTITY_IssueResultMessage)) &&
+        ('\0' != str[size - sizeof (struct GNUNET_IDENTITY_IssueResultMessage) 
- 1]) )
+    {
+      GNUNET_break (0);
+      reschedule_connect (h);
+      return;
+    }
+    if (size == sizeof (struct GNUNET_IDENTITY_IssueResultMessage))
+      str = NULL;
+
+    op = h->op_head;
+    GNUNET_CONTAINER_DLL_remove (h->op_head,
+                                h->op_tail,
+                                op);
+    GNUNET_CLIENT_receive (h->client, &message_handler, h,
+                          GNUNET_TIME_UNIT_FOREVER_REL);
+    ticket->data = str;
+    if (NULL != op->iss_cb)
+      op->iss_cb (op->cls, &ticket);
+    GNUNET_free (op);
+    break;
+   case GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT:
+    if (size < sizeof (struct GNUNET_IDENTITY_ExchangeResultMessage))
+    {
+      GNUNET_break (0);
+      reschedule_connect (h);
+      return;
+    }
+    erm = (const struct GNUNET_IDENTITY_ExchangeResultMessage *) msg;
+    str = (const char *) &erm[1];
+    if ( (size > sizeof (struct GNUNET_IDENTITY_ExchangeResultMessage)) &&
+        ('\0' != str[size - sizeof (struct 
GNUNET_IDENTITY_ExchangeResultMessage) - 1]) )
+    {
+      GNUNET_break (0);
+      reschedule_connect (h);
+      return;
+    }
+    if (size == sizeof (struct GNUNET_IDENTITY_ExchangeResultMessage))
+      str = NULL;
+
+    op = h->op_head;
+    GNUNET_CONTAINER_DLL_remove (h->op_head,
+                                h->op_tail,
+                                op);
+    GNUNET_CLIENT_receive (h->client, &message_handler, h,
+                          GNUNET_TIME_UNIT_FOREVER_REL);
+    token->data = str;
+    if (NULL != op->ex_cb)
+      op->ex_cb (op->cls, token);
+    GNUNET_free (op);
+    break;
+  
+  default:
+    GNUNET_break (0);
+    reschedule_connect (h);
+    return;
+  }
+}
+
+
+/**
+ * Schedule transmission of the next message from our queue.
+ *
+ * @param h identity handle
+ */
+static void
+transmit_next (struct GNUNET_IDENTITY_PROVIDER_Handle *h);
+
+
+/**
+ * Transmit next message to service.
+ *
+ * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle`.
+ * @param size number of bytes available in @a buf
+ * @param buf where to copy the message
+ * @return number of bytes copied to buf
+ */
+static size_t
+send_next_message (void *cls,
+                  size_t size,
+                  void *buf)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op = h->op_head;
+  size_t ret;
+
+  h->th = NULL;
+  if (NULL == op)
+    return 0;
+  ret = ntohs (op->msg->size);
+  if (ret > size)
+  {
+    reschedule_connect (h);
+    return 0;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Sending message of type %d to identity provider service\n",
+       ntohs (op->msg->type));
+  memcpy (buf, op->msg, ret);
+  if ( (NULL == op->cont) &&
+       (NULL == op->cb) )
+  {
+    GNUNET_CONTAINER_DLL_remove (h->op_head,
+                                h->op_tail,
+                                op);
+    GNUNET_free (op);
+    transmit_next (h);
+  }
+  if (GNUNET_NO == h->in_receive)
+  {
+    h->in_receive = GNUNET_YES;
+    GNUNET_CLIENT_receive (h->client,
+                          &message_handler, h,
+                          GNUNET_TIME_UNIT_FOREVER_REL);
+  }
+  return ret;
+}
+
+
+/**
+ * Schedule transmission of the next message from our queue.
+ *
+ * @param h identity provider handle
+ */
+static void
+transmit_next (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op = h->op_head;
+
+  GNUNET_assert (NULL == h->th);
+  if (NULL == op)
+    return;
+  if (NULL == h->client)
+    return;
+  h->th = GNUNET_CLIENT_notify_transmit_ready (h->client,
+                                              ntohs (op->msg->size),
+                                              GNUNET_TIME_UNIT_FOREVER_REL,
+                                              GNUNET_NO,
+                                              &send_next_message,
+                                              h);
+}
+
+
+/**
+ * Try again to connect to the service.
+ *
+ * @param cls handle to the identity provider service.
+ * @param tc scheduler context
+ */
+static void
+reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_IDENTITY_Handle *h = cls;
+  struct GNUNET_IDENTITY_Operation *op;
+  struct GNUNET_MessageHeader msg;
+
+  h->reconnect_task = NULL;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Connecting to identity provider service.\n");
+  GNUNET_assert (NULL == h->client);
+  h->client = GNUNET_CLIENT_connect ("identity-provider", h->cfg);
+  GNUNET_assert (NULL != h->client);
+  if ( (NULL == h->op_head) ||
+       (GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_START != ntohs 
(h->op_head->msg->type)) )
+  {
+    op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Operation) +
+                       sizeof (struct GNUNET_MessageHeader));
+    op->h = h;
+    op->msg = (const struct GNUNET_MessageHeader *) &op[1];
+    msg.size = htons (sizeof (msg));
+    msg.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_START);
+    memcpy (&op[1], &msg, sizeof (msg));
+    GNUNET_CONTAINER_DLL_insert (h->op_head,
+                                h->op_tail,
+                                op);
+  }
+  transmit_next (h);
+  GNUNET_assert (NULL != h->th);
+}
+
+
+/**
+ * Connect to the identity provider service.
+ *
+ * @param cfg the configuration to use
+ * @return handle to use
+ */
+struct GNUNET_IDENTITY_PROVIDER_Handle *
+GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle 
*cfg)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h;
+
+  h = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Handle);
+  h->cfg = cfg;
+  h->cb = cb;
+  h->cb_cls = cb_cls;
+  h->egos = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_YES);
+  h->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
+  h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, h);
+  return h;
+}
+
+
+/**
+ * Issue an identity token
+ *
+ * @param id identity service to query
+ * @param service_name for which service is an identity wanted
+ * @param cb function to call with the result (will only be called once)
+ * @param cb_cls closure for @a cb
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle 
*id,
+                    const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key,
+         const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+         const char* scopes,
+         const struct GNUNET_TIME_Absolute exp,
+                    GNUNET_IDENTITY_PROVIDER_IssueCallback cb,
+                    void *cb_cls)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+  struct GNUNET_IDENTITY_PROVIDER_IssueMessage *im;
+  size_t slen;
+
+  slen = strlen (scopes) + 1;
+  if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct 
GNUNET_IDENTITY_PROVIDER_IssueMessage))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Operation) +
+                     sizeof (struct GNUNET_IDENTITY_IssueMessage) +
+                     slen);
+  op->h = id;
+  op->cb = cb;
+  op->cls = cb_cls;
+  im = (struct GNUNET_IDENTITY_GetDefaultMessage *) &op[1];
+  im->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE);
+  im->header.size = htons (sizeof (struct 
GNUNET_IDENTITY_PROVIDER_IssueMessage) +
+                           slen);
+  im->iss_key = *iss_key;
+  im->aud_key = *aud_ley;
+  im->exp = exp.abs_value_ul;
+  memcpy (&im[1], scopes, slen);
+  op->msg = &im->header;
+  GNUNET_CONTAINER_DLL_insert_tail (id->op_head,
+                                   id->op_tail,
+                                   op);
+  if (NULL == id->th)
+    transmit_next (id);
+  return op;
+}
+
+
+/**
+ * Exchange a token ticket for a token
+ *
+ * @param id identity provider service
+ * @param ticket ticket to exchange
+ * @param cont function to call once the operation finished
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct GNUNET_IDENTITY_Handle *id,
+                    const char *ticket,
+                    GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont,
+                    void *cont_cls)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+  struct GNUNET_IDENTITY_PROVIDER_ExchangeMessage *em;
+  size_t slen;
+
+  slen = strlen (ticket) + 1;
+  if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct 
GNUNET_IDENTITY_ExchangeMessage))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Operation) +
+                     sizeof (struct GNUNET_IDENTITY_ExchangeMessage) +
+                     slen);
+  op->h = id;
+  op->cont = cont;
+  op->cls = cont_cls;
+  em = (struct GNUNET_IDENTITY_ExchangeMessage *) &op[1];
+  em->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE);
+  em->header.size = htons (sizeof (struct GNUNET_IDENTITY_ExchangeMessage) +
+                           slen);
+  memcpy (&em[1], ticket, slen);
+  op->msg = &em->header;
+  GNUNET_CONTAINER_DLL_insert_tail (id->op_head,
+                                   id->op_tail,
+                                   op);
+  if (NULL == id->th)
+    transmit_next (id);
+  return op;
+}
+
+
+/**
+ * Cancel an operation. Note that the operation MAY still
+ * be executed; this merely cancels the continuation; if the request
+ * was already transmitted, the service may still choose to complete
+ * the operation.
+ *
+ * @param op operation to cancel
+ */
+void
+GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op)
+{
+  struct GNUNET_IDENTITY_Handle *h = op->h;
+
+  if ( (h->op_head != op) ||
+       (NULL == h->client) )
+  {
+    /* request not active, can simply remove */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Client aborted non-head operation, simply removing it\n");
+    GNUNET_CONTAINER_DLL_remove (h->op_head,
+                                h->op_tail,
+                                op);
+    GNUNET_free (op);
+    return;
+  }
+  if (NULL != h->th)
+  {
+    /* request active but not yet with service, can still abort */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Client aborted head operation prior to transmission, aborting 
it\n");
+    GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
+    h->th = NULL;
+    GNUNET_CONTAINER_DLL_remove (h->op_head,
+                                h->op_tail,
+                                op);
+    GNUNET_free (op);
+    transmit_next (h);
+    return;
+  }
+  /* request active with service, simply ensure continuations are not called */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Client aborted active request, NULLing continuation\n");
+  op->ex_cb = NULL;
+  op->iss_cb = NULL;
+}
+
+
+/**
+ * Disconnect from service
+ *
+ * @param h handle to destroy
+ */
+void
+GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+
+  GNUNET_assert (NULL != h);
+  if (h->reconnect_task != NULL)
+  {
+    GNUNET_SCHEDULER_cancel (h->reconnect_task);
+    h->reconnect_task = NULL;
+  }
+  if (NULL != h->th)
+  {
+    GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
+    h->th = NULL;
+  }
+  while (NULL != (op = h->op_head))
+  {
+    GNUNET_break (NULL == op->cont);
+    GNUNET_CONTAINER_DLL_remove (h->op_head,
+                                h->op_tail,
+                                op);
+    GNUNET_free (op);
+  }
+  if (NULL != h->client)
+  {
+    GNUNET_CLIENT_disconnect (h->client);
+    h->client = NULL;
+  }
+  GNUNET_free (h);
+}
+
+/* end of identity_provider_api.c */

Copied: gnunet/src/identity-provider/identity_token.c (from rev 36795, 
gnunet/src/identity-provider/identity-token.c)
===================================================================
--- gnunet/src/identity-provider/identity_token.c                               
(rev 0)
+++ gnunet/src/identity-provider/identity_token.c       2016-01-08 18:59:47 UTC 
(rev 36796)
@@ -0,0 +1,828 @@
+/*
+      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 "identity_token.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 IdentityToken*
+token_create (const struct GNUNET_CRYPTO_EcdsaPublicKey* iss,
+                                       const struct 
GNUNET_CRYPTO_EcdsaPublicKey* aud)
+{
+  struct IdentityToken *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 IdentityToken));
+
+  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));
+  json_object_set_new (token->payload, "sub", json_string (issuer));
+
+  token->aud_key = *aud;
+  GNUNET_free (issuer);
+  GNUNET_free (audience);
+  return token;
+}
+
+void
+token_destroy (struct IdentityToken *token)
+{
+  json_decref (token->header);
+  json_decref (token->payload);
+  GNUNET_free (token);
+}
+
+void
+token_add_attr (const struct IdentityToken *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
+token_add_json (const struct IdentityToken *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
+token_parse2 (const char* raw_data,
+                                       const struct 
GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
+                                       const struct 
GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                                       struct IdentityToken **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 IdentityToken));
+  (*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
+token_parse (const char* raw_data,
+                                      const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                                      struct IdentityToken **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 IdentityToken));
+  (*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
+token_to_string (const struct IdentityToken *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
+token_serialize (const struct IdentityToken *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 == 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 TokenTicketPayload*
+ticket_payload_create (const char* nonce,
+                                                const struct 
GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
+                                                const char* lbl_str)
+{
+  struct TokenTicketPayload* payload;
+
+  payload = GNUNET_malloc (sizeof (struct 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
+ticket_payload_destroy (struct TokenTicketPayload* payload)
+{
+  GNUNET_free (payload->nonce);
+  GNUNET_free (payload->label);
+  GNUNET_free (payload);
+}
+
+void
+ticket_payload_serialize (struct 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 TokenTicket*
+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 TokenTicket *ticket;
+  struct TokenTicketPayload *code_payload;
+
+  ticket = GNUNET_malloc (sizeof (struct TokenTicket));
+  code_payload = ticket_payload_create (nonce_str,
+                                                                 identity_pkey,
+                                                                 lbl_str);
+  ticket->aud_key = *aud_key;
+  ticket->payload = code_payload;
+
+
+  return ticket;
+}
+
+void
+ticket_destroy (struct TokenTicket *ticket)
+{
+  ticket_payload_destroy (ticket->payload);
+  GNUNET_free (ticket);
+}
+
+int
+ticket_serialize (struct 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;
+
+  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
+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 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 = 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
+ticket_parse (const char *raw_data,
+                                       const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                                       struct 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 TokenTicket *ticket;
+  struct 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 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);
+
+
+  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))
+  {
+    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 */

Copied: gnunet/src/identity-provider/identity_token.h (from rev 36795, 
gnunet/src/include/gnunet_identity_provider_lib.h)
===================================================================
--- gnunet/src/identity-provider/identity_token.h                               
(rev 0)
+++ gnunet/src/identity-provider/identity_token.h       2016-01-08 18:59:47 UTC 
(rev 36796)
@@ -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 IDENTITY_TOKEN_H
+#define IDENTITY_TOKEN_H
+
+#include "gnunet_crypto_lib.h"
+#include <jansson.h>
+
+struct IdentityToken
+{
+  /**
+   * 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 TokenTicketPayload
+{
+  /**
+   * Nonce
+   */
+  char* nonce;
+
+  /**
+   * Label
+   */
+  char *label;
+
+  /**
+   * Issuing Identity
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity_key;
+};
+
+
+struct TokenTicket
+{
+  /**
+   * Meta info
+   */
+  struct 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 IdentityToken*
+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
+token_destroy (struct IdentityToken*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
+token_add_attr (const struct IdentityToken *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
+token_add_json (const struct IdentityToken *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 
+token_serialize (const struct IdentityToken*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
+token_parse (const char* data,
+             const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+             struct IdentityToken **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
+  token_parse2 (const char* data,
+                const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
+                const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                struct IdentityToken **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
+  token_to_string (const struct IdentityToken *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 TokenTicket*
+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
+ticket_serialize (struct TokenTicket *ticket,
+                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                  char **result);
+
+/**
+ * Destroys a ticket
+ *
+ * @param the ticket to destroy
+ */
+void
+ticket_destroy (struct 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
+  ticket_parse (const char* raw_data,
+                const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+                struct TokenTicket **ticket);
+
+#endif

Modified: gnunet/src/identity-provider/plugin_rest_identity_token.c
===================================================================
--- gnunet/src/identity-provider/plugin_rest_identity_token.c   2016-01-07 
21:10:24 UTC (rev 36795)
+++ gnunet/src/identity-provider/plugin_rest_identity_token.c   2016-01-08 
18:59:47 UTC (rev 36796)
@@ -34,7 +34,7 @@
 #include "microhttpd.h"
 #include <jansson.h>
 #include "gnunet_signatures.h"
-#include "gnunet_identity_provider_lib.h"
+#include "gnunet_identity_provider_service.h"
 
 /**
  * REST root namespace
@@ -61,7 +61,7 @@
  */
 #define GNUNET_REST_API_NS_IDENTITY_OAUTH2_AUTHORIZE "/gnuid/authorize"
 
-#define GNUNET_REST_JSONAPI_IDENTITY_token_ticket "code"
+#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET "ticket"
 
 #define GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_GRANT_TYPE_CODE 
"authorization_code"
 
@@ -213,16 +213,21 @@
   struct GNUNET_IDENTITY_Operation *op;
 
   /**
-   * Handle to NS service
+   * Identity Provider
    */
-  struct GNUNET_NAMESTORE_Handle *ns_handle;
+  struct GNUNET_IDENTITY_PROVIDER_Handle *idp;
 
   /**
-   * Handle to GNS service
+   * Idp Operation
    */
-  struct GNUNET_GNS_Handle *gns_handle;
+  struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
 
   /**
+   * Handle to NS service
+   */
+  struct GNUNET_NAMESTORE_Handle *ns_handle;
+
+  /**
    * NS iterator
    */
   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
@@ -243,11 +248,6 @@
   struct GNUNET_SCHEDULER_Task * timeout_task;    
   
   /**
-   * GNS lookup
-   */
-  struct GNUNET_GNS_LookupRequest *lookup_request;
-
-  /**
    * The plugin result processor
    */
   GNUNET_REST_ResultProcessor proc;
@@ -288,16 +288,6 @@
   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;
@@ -330,8 +320,6 @@
     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)
@@ -340,10 +328,6 @@
     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)
@@ -404,24 +388,7 @@
                   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);
-}
 
 
 
@@ -441,299 +408,45 @@
  * @return identifier string of token (label)
  */
 static void
-sign_and_return_token (void *cls,
-                       const struct GNUNET_SCHEDULER_TaskContext *tc)
+token_creat_cont (void *cls,
+                  const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
 {
-  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) )
+  char *ticket_str;
+  char *result_str;
+  struct MHD_Response *resp;
+  
+  if (NULL == ticket)
   {
-    handle->emsg = GNUNET_strdup ("Request nonce missing!\n");
+    handle->emsg = GNUNET_strdup ("Error in token issue");
     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);
+                                                    "tmpid");
+  ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket);
+  token_ticket_json = json_string (ticket_str);
   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,
+                                         
GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
                                          token_ticket_json);
-  GNUNET_free (token_ticket_str);
+  GNUNET_free (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));
+  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);
 
-  //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)
  *
@@ -749,6 +462,9 @@
   const char *egoname;
   char *ego_val;
   char *audience;
+  char *exp_str;
+  char *nonce_str;
+  char *scopes;
   struct RequestHandle *handle = cls;
   struct EgoEntry *ego_entry;
   struct GNUNET_HashCode key;
@@ -756,6 +472,10 @@
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
   struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
   struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
+  struct GNUNET_TIME_Relative etime_rel;
+  struct GNUNET_TIME_Absolute exp_time;
+  uint64_t time;
+  uint64_t nonce;
 
   if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url,
                                                 
GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE))
@@ -806,6 +526,24 @@
                       strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST),
                       &key);
 
+  //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 audience
   audience = NULL;
   if ( GNUNET_YES !=
@@ -829,18 +567,79 @@
                                  strlen (audience),
                                  &aud_key,
                                  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  handle->token = GNUNET_IDENTITY_PROVIDER_token_create (&pub_key,
-                                                         aud_key);
+
+  //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);
+  sscanf (nonce_str, "%lu", &nonce);
+
+  //Get expiration for token from URL parameter
+  GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING,
+                      strlen (GNUNET_IDENTITY_TOKEN_EXP_STRING),
+                      &key);
+
+  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.abs_value_us = time + etime_rel.rel_value_us;
+
+  handle->idp_op = GNUNET_IDENTITY_PROVIDER_issue_token (handle->idp,
+                                                         priv_key,
+                                                         aud_key,
+                                                         scopes,
+                                                         &exp_time,
+                                                         nonce,
+                                                         &token_creat_cont,
+                                                         handle);
+  /*handle->token_handle = GNUNET_IDENTITY_PROVIDER_token_issue (&pub_key,
+    aud_key,
+    handle->attr_map,
+    &token_creat_cont,
+    handle);
+    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);
+  /*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);*/
 }
 
 
@@ -1010,51 +809,21 @@
 
 }
 
-
-
-
 static void
-process_lookup_result (void *cls, uint32_t rd_count,
-                       const struct GNUNET_GNSRECORD_Data *rd)
+exchange_cont (void *cls,
+              const struct GNUNET_IDENTITY_PROVIDER_Token *token)
 {
+  json_t *root;
   struct RequestHandle *handle = cls;
-  json_t *root;
   struct MHD_Response *resp;
-  char *result;
+  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));
-
+  
+  root = json_object ();
+  token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token);
   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);
@@ -1062,32 +831,31 @@
   GNUNET_free (result);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   cleanup_handle (handle);
-  json_decref (root);
+  json_decref (root); 
 }
 
-
 static void
 exchange_token_ticket_cb (void *cls,
-                        struct GNUNET_IDENTITY_Ego *ego,
-                        void **ctx,
-                        const char *name)
+                          struct GNUNET_IDENTITY_Ego *ego,
+                          void **ctx,
+                          const char *name)
 {
   struct RequestHandle *handle = cls;
   struct GNUNET_HashCode key;
-  char* code;
-  char* lookup_query;
+  struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
+  char* ticket_str;
 
   handle->op = NULL;
 
   if (NULL == ego)
   {
-    handle->emsg = GNUNET_strdup ("No GNS identity found.");
+    handle->emsg = GNUNET_strdup ("No 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),
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
+                      strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET),
                       &key);
 
   if ( GNUNET_NO ==
@@ -1094,38 +862,28 @@
        GNUNET_CONTAINER_multihashmap_contains 
(handle->conndata_handle->url_param_map,
                                                &key) )
   {
-    handle->emsg = GNUNET_strdup ("No code given.");
+    handle->emsg = GNUNET_strdup ("No ticket given.");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  code = GNUNET_CONTAINER_multihashmap_get 
(handle->conndata_handle->url_param_map,
+  ticket_str = GNUNET_CONTAINER_multihashmap_get 
(handle->conndata_handle->url_param_map,
                                             &key);
 
   handle->priv_key = GNUNET_IDENTITY_ego_get_private_key (ego);
+  GNUNET_IDENTITY_PROVIDER_string_to_ticket (ticket_str,
+                                             &ticket);
 
-  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);
+  handle->idp_op = GNUNET_IDENTITY_PROVIDER_exchange_ticket (handle->idp,
+                                                             ticket,
+                                                             handle->priv_key,
+                                                             &exchange_cont,
+                                                             handle);
+  GNUNET_free (ticket);
+
 }
 
+
+
 /**
  * Respond to OAuth2 /token request
  *
@@ -1135,8 +893,8 @@
  */
 static void
 exchange_token_ticket_cont (struct RestConnectionDataHandle *con_handle,
-                          const char* url,
-                          void *cls)
+                            const char* url,
+                            void *cls)
 {
   struct RequestHandle *handle = cls;
   char* grant_type;

Deleted: gnunet/src/include/gnunet_identity_provider_lib.h
===================================================================
--- gnunet/src/include/gnunet_identity_provider_lib.h   2016-01-07 21:10:24 UTC 
(rev 36795)
+++ gnunet/src/include/gnunet_identity_provider_lib.h   2016-01-08 18:59:47 UTC 
(rev 36796)
@@ -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

Added: gnunet/src/include/gnunet_identity_provider_service.h
===================================================================
--- gnunet/src/include/gnunet_identity_provider_service.h                       
        (rev 0)
+++ gnunet/src/include/gnunet_identity_provider_service.h       2016-01-08 
18:59:47 UTC (rev 36796)
@@ -0,0 +1,202 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2016 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 include/gnunet_identity_provider_service.h
+ * @brief Identity provider service; implements identity provider for GNUnet
+ * @author Martin Schanzenbach
+ *
+ * Egos in GNUnet are ECDSA keys.  You assume an ego by using (signing
+ * with) a particular private key.  As GNUnet users are expected to
+ * have many egos, we need an identity service to allow users to
+ * manage their egos.  The identity service manages the egos (private
+ * keys) of the local user; it does NOT manage egos of other users
+ * (public keys).  For giving names to other users and manage their
+ * public keys securely, we use GNS.
+ *
+ * @defgroup identity-provider service
+ * @{
+ */
+#ifndef GNUNET_IDENTITY_PROVIDER_SERVICE_H
+#define GNUNET_IDENTITY_PROVIDER_SERVICE_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "gnunet_util_lib.h"
+
+
+/**
+ * Version number of GNUnet Identity Provider API.
+ */
+#define GNUNET_IDENTITY_PROVIDER_VERSION 0x00000000
+
+/**
+ * Handle to access the identity service.
+ */
+struct GNUNET_IDENTITY_PROVIDER_Handle;
+
+/**
+ * Handle for a token.
+ */
+struct GNUNET_IDENTITY_PROVIDER_Token;
+
+/**
+ * Handle for a ticket
+ */
+struct GNUNET_IDENTITY_PROVIDER_Ticket;
+
+/**
+ * Handle for an operation with the identity provider service.
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation;
+
+/**
+ * Method called when a token has been exchanged for a ticket.
+ * On success returns a token
+ *
+ * @param cls closure
+ * @param token the token
+ */
+typedef void
+(*GNUNET_IDENTITY_PROVIDER_ExchangeCallback)(void *cls,
+                            const struct GNUNET_IDENTITY_PROVIDER_Token 
*token);
+
+/**
+ * Method called when a token has been issued.
+ * On success returns a ticket that can be given to the audience to retrive the
+ * token
+ *
+ * @param cls closure
+ * @param ticket the ticket
+ * @param name name assigned by the user for this ego,
+ *                   NULL if the user just deleted the ego and it
+ *                   must thus no longer be used
+ */
+typedef void
+(*GNUNET_IDENTITY_PROVIDER_IssueCallback)(void *cls,
+                            const struct GNUNET_IDENTITY_PROVIDER_Ticket 
*ticket);
+
+
+/**
+ * Connect to the identity provider service.
+ *
+ * @param cfg Configuration to contact the identity provider service.
+ * @return handle to communicate with identity provider service
+ */
+struct GNUNET_IDENTITY_PROVIDER_Handle *
+GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle 
*cfg);
+
+
+/**
+ * Issue a token for a specific audience.
+ *
+ * @param id identity provider service to use
+ * @param iss issuer (identity)
+ * @param aud audience (identity)
+ * @param scope the identity attributes requested, comman separated
+ * @param expiration the token expiration
+ * @param nonce the nonce that will be included in token and ticket
+ * @param cb callback to call with result
+ * @param cb_cls closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle 
*id,
+                    const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key,
+         const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+         const char* scope,
+         struct GNUNET_TIME_Absolute *expiration,
+         uint64_t nonce,
+                    GNUNET_IDENTITY_PROVIDER_IssueCallback cb,
+                    void *cb_cls);
+
+
+/**
+ * Exchange a ticket for a token. Intended to be used by audience that
+ * received a ticket.
+ *
+ * @param id identity provider service to use
+ * @param ticket the ticket to exchange
+ * @param aud_privkey the audience of the ticket
+ * @param cont function to call once the operation finished
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct 
GNUNET_IDENTITY_PROVIDER_Handle *id,
+                    const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+         const struct GNUNET_CRYPTO_EcdsaPrivateKey *aud_privkey,
+                    GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont,
+                    void *cont_cls);
+
+
+/**
+ * Disconnect from identity provider service.
+ *
+ * @param h identity provider service to disconnect
+ */
+void
+GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle 
*h);
+
+
+/**
+ * Cancel an identity provider operation.  Note that the operation MAY still
+ * be executed; this merely cancels the continuation; if the request
+ * was already transmitted, the service may still choose to complete
+ * the operation.
+ *
+ * @param op operation to cancel
+ */
+void
+GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation 
*op);
+
+
+/**
+ * Convenience API
+ */
+char *
+GNUNET_IDENTITY_PROVIDER_token_to_string (const struct 
GNUNET_IDENTITY_PROVIDER_Token *token);
+
+char *
+GNUNET_IDENTITY_PROVIDER_ticket_to_string (const struct 
GNUNET_IDENTITY_PROVIDER_Ticket *ticket);
+
+
+int
+GNUNET_IDENTITY_PROVIDER_string_to_ticket (const char* input,
+                                           struct 
GNUNET_IDENTITY_PROVIDER_Ticket **ticket);
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */ /* end of group identity */
+
+/* ifndef GNUNET_IDENTITY_PROVIDER_SERVICE_H */
+#endif
+/* end of gnunet_identity_provider_service.h */

Modified: gnunet/src/include/gnunet_protocols.h
===================================================================
--- gnunet/src/include/gnunet_protocols.h       2016-01-07 21:10:24 UTC (rev 
36795)
+++ gnunet/src/include/gnunet_protocols.h       2016-01-08 18:59:47 UTC (rev 
36796)
@@ -2822,8 +2822,23 @@
 
 
/*******************************************************************************/
 
+
+/**************************************************
+ *
+ * IDENTITY PROVIDER MESSAGE TYPES
+ */
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE     961
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE  962
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT     963
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT  964
+
+/*******************************************************************************/
+
 /**
- * Next available: 960
+ * Next available: 970
  */
 
 /**




reply via email to

[Prev in Thread] Current Thread [Next in Thread]