gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r36674 - gnunet/src/identity-token


From: gnunet
Subject: [GNUnet-SVN] r36674 - gnunet/src/identity-token
Date: Thu, 19 Nov 2015 13:18:35 +0100

Author: schanzen
Date: 2015-11-19 13:18:35 +0100 (Thu, 19 Nov 2015)
New Revision: 36674

Added:
   gnunet/src/identity-token/gnunet-service-identity-token.c
Modified:
   gnunet/src/identity-token/Makefile.am
   gnunet/src/identity-token/identity-token.conf
Log:
-add identity token service

Modified: gnunet/src/identity-token/Makefile.am
===================================================================
--- gnunet/src/identity-token/Makefile.am       2015-11-18 22:15:53 UTC (rev 
36673)
+++ gnunet/src/identity-token/Makefile.am       2015-11-19 12:18:35 UTC (rev 
36674)
@@ -27,6 +27,20 @@
 bin_PROGRAMS = \
  gnunet-identity-token
 
+libexec_PROGRAMS = \
+ gnunet-service-identity-token
+
+gnunet_service_identity_token_SOURCES = \
+ gnunet-service-identity-token.c
+
+gnunet_service_identity_token_LDADD = \
+ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/identity/libgnunetidentity.la \
+ $(GN_LIBINTL) \
+ -ljansson
+
 libgnunet_plugin_rest_identity_token_la_SOURCES = \
   plugin_rest_identity_token.c
 libgnunet_plugin_rest_identity_token_la_LIBADD = \

Added: gnunet/src/identity-token/gnunet-service-identity-token.c
===================================================================
--- gnunet/src/identity-token/gnunet-service-identity-token.c                   
        (rev 0)
+++ gnunet/src/identity-token/gnunet-service-identity-token.c   2015-11-19 
12:18:35 UTC (rev 36674)
@@ -0,0 +1,453 @@
+/*
+   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"
+
+#define STATE_INIT 0
+
+#define STATE_POST_INIT 1
+
+#define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
+
+static int state;
+
+static struct EgoEntry *ego_head;
+
+static struct EgoEntry *ego_tail;
+
+static struct GNUNET_IDENTITY_Handle *identity_handle;
+
+static struct GNUNET_NAMESTORE_Handle *ns_handle;
+
+static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+static struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+
+static struct GNUNET_SCHEDULER_Task * timeout_task;
+
+static struct GNUNET_SCHEDULER_Task * update_task;
+
+static struct GNUNET_TIME_Relative min_rel_exp;
+
+static char* token;
+
+static char* label;
+
+struct EgoEntry
+{
+  struct EgoEntry *next;
+  struct EgoEntry *prev;
+  struct GNUNET_IDENTITY_Ego *ego;
+};
+
+/**
+ * Our configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+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_log (GNUNET_ERROR_TYPE_ERROR, ">>> Next token\n");
+  GNUNET_NAMESTORE_zone_iterator_next (ns_it);
+}
+
+static void
+handle_token_update (void *cls,
+                     const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  char *token_header;
+  char *token_payload;
+  char *token_payload_json;
+  char *new_token;
+  char *new_payload_str;
+  char *new_payload_base64;
+  char *sig_str;
+  char *key;
+  char *padding;
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+  struct EgoEntry *ego_entry = cls;
+  struct GNUNET_GNSRECORD_Data token_record;
+  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
+  struct GNUNET_CRYPTO_EcdsaSignature sig;
+  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;
+  json_t *payload_json;
+  json_t *value;
+  json_t *new_payload_json;
+  json_t *token_nbf_json;
+  json_t *token_exp_json;
+  json_error_t json_err;
+
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+
+  //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.
+
+  token_header = strtok (token, ".");
+
+  token_payload = strtok (NULL, ".");
+
+  GNUNET_STRINGS_base64_decode (token_payload,
+                                strlen (token_payload),
+                                &token_payload_json);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Payload: %s\n",
+              token_payload_json);
+  payload_json = json_loads (token_payload_json, JSON_DECODE_ANY, &json_err);
+  GNUNET_free (token_payload_json);
+
+  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_NAMESTORE_zone_iterator_next (ns_it);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Token is expired. Create a new one\n");
+  new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp);
+  new_nbf = GNUNET_TIME_absolute_get ();
+  new_iat = new_nbf;
+  new_payload_json = json_object();
+  json_object_foreach(payload_json, key, value) {
+    if (0 == strcmp (key, "exp"))
+    {
+      json_object_set_new (new_payload_json, key, json_integer 
(new_exp.abs_value_us));
+    }
+    else if (0 == strcmp (key, "nbf"))
+    {
+      json_object_set_new (new_payload_json, key, json_integer 
(new_nbf.abs_value_us));
+    }
+    else if (0 == strcmp (key, "iat"))
+    {
+      json_object_set_new (new_payload_json, key, json_integer 
(new_iat.abs_value_us));
+    }
+    else {
+      json_object_set_new (new_payload_json, key, value);
+    }
+  }
+  json_decref (payload_json);
+
+  // reassemble and set
+  new_payload_str = json_dumps (new_payload_json, JSON_COMPACT);
+  json_decref (new_payload_json);
+  GNUNET_STRINGS_base64_encode (new_payload_str,
+                                strlen (new_payload_str),
+                                &new_payload_base64);
+  //Remove padding
+  padding = strtok(new_payload_base64, "=");
+  while (NULL != padding)
+    padding = strtok(NULL, "=");
+
+  GNUNET_asprintf (&new_token, "%s,%s", token_header, new_payload_base64);
+  purpose =
+    GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
+                   strlen (new_token));
+  purpose->size =
+    htonl (strlen (new_token) + sizeof (struct 
GNUNET_CRYPTO_EccSignaturePurpose));
+  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
+  memcpy (&purpose[1], new_token, strlen (new_token));
+  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
+                                             purpose,
+                                             &sig))
+    GNUNET_break(0);
+  GNUNET_free (new_token);
+  sig_str = GNUNET_STRINGS_data_to_string_alloc (&sig,
+                                                 sizeof (struct 
GNUNET_CRYPTO_EcdsaSignature));
+  GNUNET_asprintf (&new_token, "%s.%s.%s",
+                   token_header, new_payload_base64, sig_str);
+  GNUNET_free (sig_str);
+  GNUNET_free (new_payload_str);
+  GNUNET_free (new_payload_base64);
+  GNUNET_free (purpose);
+
+  token_record.data = new_token;
+  token_record.data_size = strlen (new_token);
+  token_record.expiration_time = new_exp.abs_value_us;
+  token_record.record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN;
+  token_record.flags = GNUNET_GNSRECORD_RF_NONE | 
GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+  ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                          priv_key,
+                                          label,
+                                          1,
+                                          &token_record,
+                                          &store_token_cont,
+                                          ego_entry);
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Updating Token w/ %s\n", 
new_token);
+  GNUNET_free (new_token);
+  GNUNET_free (token);
+  token = NULL;
+  GNUNET_free (label);
+  label = NULL;
+}
+
+static void
+update_identities(void *cls,
+                  const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+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;
+
+  if (NULL == lbl)
+  {
+    //Done
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                ">>> Updating Ego finished\n");
+    GNUNET_SCHEDULER_add_now (&update_identities, ego_entry->next);
+    return;
+  }
+
+  //TODO autopurge expired tokens here if set in config
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Found record\n");
+  //There should be only a single record for a token under a label
+  if (1 != rd_count || (rd->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN))
+  {
+    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
+    return;
+  }
+  token = GNUNET_GNSRECORD_value_to_string (rd->record_type,
+                                            rd->data,
+                                            rd->data_size);
+  label = GNUNET_strdup (lbl); 
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got token: %s\n", token);
+
+  GNUNET_SCHEDULER_add_now (&handle_token_update, ego_entry);
+}
+
+
+
+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_ERROR, ">>> 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);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Updating Ego\n");
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego);
+  ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
+                                                 priv_key,
+                                                 &token_collect,
+                                                 next_ego);
+}
+
+
+/* ************************* Global helpers ********************* */
+
+static void
+init_cont ()
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Starting Service\n");
+  //Initially iterate all itenties and refresh all tokens
+  update_task = GNUNET_SCHEDULER_add_now (&update_identities, ego_head);
+}
+
+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;
+    GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry);
+  }
+}
+
+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;
+    ego_entry = ego_entry->next;
+    GNUNET_free (ego_tmp);
+  }
+}
+
+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 connectin 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 */

Modified: gnunet/src/identity-token/identity-token.conf
===================================================================
--- gnunet/src/identity-token/identity-token.conf       2015-11-18 22:15:53 UTC 
(rev 36673)
+++ gnunet/src/identity-token/identity-token.conf       2015-11-19 12:18:35 UTC 
(rev 36674)
@@ -1 +1,2 @@
 [identity-token]
+BINARY=gnunet-service-identity-token




reply via email to

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