[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
*/
/**
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r36796 - in gnunet/src: identity-provider include,
gnunet <=