summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorxrs <xrs@mail36.net>2020-01-16 17:12:09 +0100
committerxrs <xrs@mail36.net>2020-01-16 17:12:09 +0100
commit32b55237f2b94b4940d7031a0bc1adcf8b63824a (patch)
tree92766aa532ef2c674192dc3bd0e9b71a99829fa1 /src
parentec78709681261eaddedbed6484dd95849f180f92 (diff)
parent5177efb74f9301bbffd79d63f47eb78611e6abba (diff)
Merge branch 'master' of ssh://git.gnunet.org/gnunet
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am8
-rw-r--r--src/curl/curl.c2
-rw-r--r--src/gns/gns.h8
-rw-r--r--src/gns/gns_api.c68
-rw-r--r--src/gns/gnunet-service-gns.c1
-rw-r--r--src/gns/gnunet-service-gns_interceptor.c7
-rw-r--r--src/gns/gnunet-service-gns_resolver.c23
-rw-r--r--src/gns/gnunet-service-gns_resolver.h5
-rw-r--r--src/include/Makefile.am16
-rw-r--r--src/include/gnunet_buffer_lib.h176
-rw-r--r--src/include/gnunet_curl_lib.h2
-rw-r--r--src/include/gnunet_gns_service.h25
-rw-r--r--src/include/gnunet_gnsrecord_lib.h11
-rw-r--r--src/include/gnunet_protocols.h11
-rw-r--r--src/include/gnunet_reclaim_attribute_lib.h245
-rw-r--r--src/include/gnunet_reclaim_attribute_plugin.h27
-rw-r--r--src/include/gnunet_reclaim_service.h82
-rw-r--r--src/include/gnunet_util_taler_wallet_lib.h56
-rw-r--r--src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c109
-rw-r--r--src/reclaim-attribute/reclaim_attribute.c587
-rw-r--r--src/reclaim-attribute/reclaim_attribute.h62
-rw-r--r--src/reclaim/gnunet-reclaim.c14
-rw-r--r--src/reclaim/gnunet-service-reclaim.c903
-rw-r--r--src/reclaim/gnunet-service-reclaim_tickets.c260
-rw-r--r--src/reclaim/json_reclaim.c221
-rw-r--r--src/reclaim/json_reclaim.h19
-rw-r--r--src/reclaim/oidc_helper.c126
-rw-r--r--src/reclaim/oidc_helper.h2
-rw-r--r--src/reclaim/plugin_gnsrecord_reclaim.c6
-rw-r--r--src/reclaim/plugin_rest_openid_connect.c236
-rw-r--r--src/reclaim/plugin_rest_reclaim.c867
-rw-r--r--src/reclaim/reclaim.h39
-rw-r--r--src/reclaim/reclaim_api.c418
-rw-r--r--src/transport/Makefile.am24
-rw-r--r--src/transport/test_communicator_unix_basic_peer1.conf (renamed from src/transport/test_communicator_unix_peer1.conf)0
-rw-r--r--src/util/.gitignore2
-rw-r--r--src/util/Makefile.am47
-rw-r--r--src/util/buffer.c226
-rw-r--r--src/util/common_logging.c8
-rw-r--r--src/util/crypto_ecc.c109
-rw-r--r--src/util/gnunet-crypto-tvg.c278
-rw-r--r--src/util/test_crypto_ecdh_ecdsa.c97
-rw-r--r--src/util/tweetnacl-gnunet.c20
-rw-r--r--src/util/tweetnacl-gnunet.h4
-rw-r--r--src/vpn/gnunet-service-vpn.c17
45 files changed, 5008 insertions, 466 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 1bcc1ae7b..7b73a4bb8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -66,12 +66,6 @@ endif
endif
-if TALER_ONLY
-SUBDIRS = \
- include \
- util
-else
-
SUBDIRS = \
include $(INTLEMU_SUBDIRS) \
util \
@@ -128,5 +122,3 @@ SUBDIRS = \
$(RECLAIM_DIR) \
$(EXP_DIR) \
integration-tests
-
-endif
diff --git a/src/curl/curl.c b/src/curl/curl.c
index dcbb43f58..82eb28ed9 100644
--- a/src/curl/curl.c
+++ b/src/curl/curl.c
@@ -680,7 +680,7 @@ do_benchmark (CURLMsg *cmsg)
/**
- * Run the main event loop for the Taler interaction.
+ * Run the main event loop for the HTTP interaction.
*
* @param ctx the library context
* @param rp parses the raw response returned from
diff --git a/src/gns/gns.h b/src/gns/gns.h
index 1fa812c23..5f51b7108 100644
--- a/src/gns/gns.h
+++ b/src/gns/gns.h
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2012-2013 GNUnet e.V.
+ Copyright (C) 2012-2020 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -57,9 +57,11 @@ struct LookupMessage
int16_t options GNUNET_PACKED;
/**
- * Always 0.
+ * Recursion depth limit, i.e. how many more
+ * GNS zones may be traversed during the resolution
+ * of this name.
*/
- int16_t reserved GNUNET_PACKED;
+ uint16_t recursion_depth_limit GNUNET_PACKED;
/**
* the type of record to look up
diff --git a/src/gns/gns_api.c b/src/gns/gns_api.c
index 4a4003b2a..0d99d822e 100644
--- a/src/gns/gns_api.c
+++ b/src/gns/gns_api.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2009-2013, 2016, 2018 GNUnet e.V.
+ Copyright (C) 2009-2020 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -37,6 +37,12 @@
#define LOG(kind, ...) GNUNET_log_from (kind, "gns-api", __VA_ARGS__)
/**
+ * Default recursion depth limit to apply if
+ * the application does not specify any.
+ */
+#define DEFAULT_LIMIT 128
+
+/**
* Handle to a lookup request
*/
struct GNUNET_GNS_LookupRequest
@@ -325,21 +331,24 @@ GNUNET_GNS_lookup_cancel (struct GNUNET_GNS_LookupRequest *lr)
*
* @param handle handle to the GNS service
* @param name the name to look up (in UTF-8 encoding)
- * @param zone the zone to start the resolution in
- * @param type the record type to look up
+ * @param zone zone to look in
+ * @param type the GNS record type to look for
* @param options local options for the lookup
- * @param proc processor to call on result
+ * @param recursion_depth_limit maximum number of zones
+ * that the lookup may (still) traverse
+ * @param proc function to call on result
* @param proc_cls closure for @a proc
- * @return handle to the get request
+ * @return handle to the queued request
*/
-struct GNUNET_GNS_LookupRequest*
-GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
- const char *name,
- const struct GNUNET_CRYPTO_EcdsaPublicKey *zone,
- uint32_t type,
- enum GNUNET_GNS_LocalOptions options,
- GNUNET_GNS_LookupResultProcessor proc,
- void *proc_cls)
+struct GNUNET_GNS_LookupRequest *
+GNUNET_GNS_lookup_limited (struct GNUNET_GNS_Handle *handle,
+ const char *name,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *zone,
+ uint32_t type,
+ enum GNUNET_GNS_LocalOptions options,
+ uint16_t recursion_depth_limit,
+ GNUNET_GNS_LookupResultProcessor proc,
+ void *proc_cls)
{
/* IPC to shorten gns names, return shorten_handle */
struct LookupMessage *lookup_msg;
@@ -370,6 +379,8 @@ GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
GNUNET_MESSAGE_TYPE_GNS_LOOKUP);
lookup_msg->id = htonl (lr->r_id);
lookup_msg->options = htons ((uint16_t) options);
+ lookup_msg->recursion_depth_limit
+ = htons (recursion_depth_limit);
lookup_msg->zone = *zone;
lookup_msg->type = htonl (type);
GNUNET_memcpy (&lookup_msg[1],
@@ -385,4 +396,35 @@ GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
}
+/**
+ * Perform an asynchronous lookup operation on the GNS.
+ *
+ * @param handle handle to the GNS service
+ * @param name the name to look up (in UTF-8 encoding)
+ * @param zone the zone to start the resolution in
+ * @param type the record type to look up
+ * @param options local options for the lookup
+ * @param proc processor to call on result
+ * @param proc_cls closure for @a proc
+ * @return handle to the get request
+ */
+struct GNUNET_GNS_LookupRequest*
+GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
+ const char *name,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *zone,
+ uint32_t type,
+ enum GNUNET_GNS_LocalOptions options,
+ GNUNET_GNS_LookupResultProcessor proc,
+ void *proc_cls)
+{
+ return GNUNET_GNS_lookup_limited (handle,
+ name,
+ zone,
+ type,
+ options,
+ DEFAULT_LIMIT,
+ proc,
+ proc_cls);
+}
+
/* end of gns_api.c */
diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c
index 99cdbfe4e..8c5b2d6c4 100644
--- a/src/gns/gnunet-service-gns.c
+++ b/src/gns/gnunet-service-gns.c
@@ -463,6 +463,7 @@ handle_lookup (void *cls,
name,
(enum GNUNET_GNS_LocalOptions) ntohs (
sh_msg->options),
+ ntohs (sh_msg->recursion_depth_limit),
&send_lookup_response, clh);
GNUNET_STATISTICS_update (statistics,
"Lookup attempts",
diff --git a/src/gns/gnunet-service-gns_interceptor.c b/src/gns/gnunet-service-gns_interceptor.c
index dd97782ae..9d6636e84 100644
--- a/src/gns/gnunet-service-gns_interceptor.c
+++ b/src/gns/gnunet-service-gns_interceptor.c
@@ -34,6 +34,12 @@
/**
+ * How deep do we allow recursions to go before we abort?
+ */
+#define MAX_RECURSION 256
+
+
+/**
* Handle to a DNS intercepted
* reslution request
*/
@@ -347,6 +353,7 @@ handle_dns_request (void *cls,
p->queries[0].type,
p->queries[0].name,
GNUNET_NO,
+ MAX_RECURSION,
&reply_to_dns, ilh);
return;
}
diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c
index 2c2263e58..735742283 100644
--- a/src/gns/gnunet-service-gns_resolver.c
+++ b/src/gns/gnunet-service-gns_resolver.c
@@ -77,11 +77,6 @@
*/
#define DHT_GNS_REPLICATION_LEVEL 10
-/**
- * How deep do we allow recursions to go before we abort?
- */
-#define MAX_RECURSION 256
-
/**
* DLL to hold the authority chain we had to pass in the resolution
@@ -320,7 +315,7 @@ struct GNS_ResolverHandle
/**
* closure passed to @e proc
*/
- void*proc_cls;
+ void *proc_cls;
/**
* Handle for DHT lookups. should be NULL if no lookups are in progress
@@ -395,7 +390,7 @@ struct GNS_ResolverHandle
struct DnsResult *dns_result_tail;
/**
- * Current offset in 'name' where we are resolving.
+ * Current offset in @e name where we are resolving.
*/
size_t name_resolution_pos;
@@ -423,12 +418,17 @@ struct GNS_ResolverHandle
/**
* We increment the loop limiter for each step in a recursive
- * resolution. If it passes our threshold (i.e. due to
+ * resolution. If it passes our @e loop_threshold (i.e. due to
* self-recursion in the resolution, i.e CNAME fun), we stop.
*/
unsigned int loop_limiter;
/**
+ * Maximum value of @e loop_limiter allowed by client.
+ */
+ unsigned int loop_threshold;
+
+ /**
* 16 bit random ID we used in the @e dns_request.
*/
uint16_t original_dns_id;
@@ -1856,6 +1856,7 @@ recursive_gns2dns_resolution (struct GNS_ResolverHandle *rh,
gp->rh->record_type = GNUNET_GNSRECORD_TYPE_ANY;
gp->rh->options = GNUNET_GNS_LO_DEFAULT;
gp->rh->loop_limiter = rh->loop_limiter + 1;
+ gp->rh->loop_threshold = rh->loop_threshold;
gp->rh->task_id
= GNUNET_SCHEDULER_add_now (&start_resolver_lookup,
gp->rh);
@@ -2744,7 +2745,7 @@ recursive_resolution (void *cls)
struct GNS_ResolverHandle *rh = cls;
rh->task_id = NULL;
- if (MAX_RECURSION < rh->loop_limiter++)
+ if (rh->loop_threshold < rh->loop_limiter++)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Encountered unbounded recursion resolving `%s'\n",
@@ -2840,6 +2841,8 @@ start_resolver_lookup (void *cls)
* @param record_type the record type to look up
* @param name the name to look up
* @param options local options to control local lookup
+ * @param recursion_depth_limit how many zones to traverse
+ * at most
* @param proc the processor to call on result
* @param proc_cls the closure to pass to @a proc
* @return handle to cancel operation
@@ -2849,6 +2852,7 @@ GNS_resolver_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *zone,
uint32_t record_type,
const char *name,
enum GNUNET_GNS_LocalOptions options,
+ uint16_t recursion_depth_limit,
GNS_ResultProcessor proc,
void *proc_cls)
{
@@ -2868,6 +2872,7 @@ GNS_resolver_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *zone,
rh->record_type = record_type;
rh->name = GNUNET_strdup (name);
rh->name_resolution_pos = strlen (name);
+ rh->loop_threshold = recursion_depth_limit;
rh->task_id = GNUNET_SCHEDULER_add_now (&start_resolver_lookup,
rh);
return rh;
diff --git a/src/gns/gnunet-service-gns_resolver.h b/src/gns/gnunet-service-gns_resolver.h
index cc918fd90..3dab3c91a 100644
--- a/src/gns/gnunet-service-gns_resolver.h
+++ b/src/gns/gnunet-service-gns_resolver.h
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2009-2013 GNUnet e.V.
+ Copyright (C) 2009-2020 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -79,6 +79,8 @@ typedef void
* @param record_type the record type to look up
* @param name the name to look up
* @param options options set to control local lookup
+ * @param recursion_depth_limit how many zones to traverse
+ * at most
* @param proc the processor to call
* @param proc_cls the closure to pass to @a proc
* @return handle to cancel operation
@@ -88,6 +90,7 @@ GNS_resolver_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *zone,
uint32_t record_type,
const char *name,
enum GNUNET_GNS_LocalOptions options,
+ uint16_t recursion_depth_limit,
GNS_ResultProcessor proc,
void *proc_cls);
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index c81f8e7d8..b53f2420d 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -9,17 +9,6 @@ EXTRA_DIST = \
block_dns.h \
block_regex.h
-if TALER_ONLY
-gnunetinclude_HEADERS = \
- platform.h gettext.h \
- gnunet_common.h \
- gnunet_container_lib.h \
- gnunet_crypto_lib.h \
- gnunet_strings_lib.h \
- gnunet_time_lib.h \
- gnunet_util_taler_wallet_lib.h
-else
-
gnunetinclude_HEADERS = \
platform.h gettext.h \
compat.h \
@@ -35,6 +24,7 @@ gnunetinclude_HEADERS = \
gnunet_block_lib.h \
gnunet_block_group_lib.h \
gnunet_block_plugin.h \
+ gnunet_buffer_lib.h \
gnunet_client_lib.h \
gnunet_common.h \
gnunet_constants.h \
@@ -101,7 +91,7 @@ gnunetinclude_HEADERS = \
gnunet_regex_service.h \
gnunet_rest_lib.h \
gnunet_rest_plugin.h \
- gnunet_rps_service.h \
+ gnunet_rps_service.h \
gnunet_revocation_service.h \
gnunet_scalarproduct_service.h \
gnunet_scheduler_lib.h \
@@ -130,5 +120,3 @@ gnunetinclude_HEADERS = \
gnunet_tun_lib.h \
gnunet_util_lib.h \
gnunet_vpn_service.h
-
-endif
diff --git a/src/include/gnunet_buffer_lib.h b/src/include/gnunet_buffer_lib.h
new file mode 100644
index 000000000..c0ae06d77
--- /dev/null
+++ b/src/include/gnunet_buffer_lib.h
@@ -0,0 +1,176 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2020 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * Common buffer management functions.
+ *
+ * @author Florian Dold
+ */
+
+#ifndef GNUNET_BUFFER_LIB_H
+#define GNUNET_BUFFER_LIB_H
+
+/**
+ * Dynamically growing buffer. Can be used to construct
+ * strings and other objects with dynamic size.
+ *
+ * This structure should, in most cases, be stack-allocated and
+ * zero-initialized, like:
+ *
+ * struct GNUNET_Buffer my_buffer = { 0 };
+ */
+struct GNUNET_Buffer
+{
+ /**
+ * Capacity of the buffer.
+ */
+ size_t capacity;
+
+ /**
+ * Current write position.
+ */
+ size_t position;
+
+ /**
+ * Backing memory.
+ */
+ char *mem;
+
+ /**
+ * Log a warning if the buffer is grown over its initially allocated capacity.
+ */
+ int warn_grow;
+};
+
+
+/**
+ * Initialize a buffer with the given capacity.
+ *
+ * When a buffer is allocated with this function, a warning is logged
+ * when the buffer exceeds the initial capacity.
+ *
+ * @param buf the buffer to initialize
+ * @param capacity the capacity (in bytes) to allocate for @a buf
+ */
+void
+GNUNET_buffer_prealloc (struct GNUNET_Buffer *buf, size_t capacity);
+
+
+/**
+ * Make sure that at least @a n bytes remaining in the buffer.
+ *
+ * @param buf buffer to potentially grow
+ * @param n number of bytes that should be available to write
+ */
+void
+GNUNET_buffer_ensure_remaining (struct GNUNET_Buffer *buf, size_t n);
+
+
+/**
+ * Write bytes to the buffer.
+ *
+ * Grows the buffer if necessary.
+ *
+ * @param buf buffer to write to
+ * @param data data to read from
+ * @param len number of bytes to copy from @a data to @a buf
+ *
+ */
+void
+GNUNET_buffer_write (struct GNUNET_Buffer *buf, const char *data, size_t len);
+
+
+/**
+ * Write a 0-terminated string to a buffer, excluding the 0-terminator.
+ *
+ * Grows the buffer if necessary.
+ *
+ * @param buf the buffer to write to
+ * @param str the string to write to @a buf
+ */
+void
+GNUNET_buffer_write_str (struct GNUNET_Buffer *buf, const char *str);
+
+
+/**
+ * Write a path component to a buffer, ensuring that
+ * there is exactly one slash between the previous contents
+ * of the buffer and the new string.
+ *
+ * @param buf buffer to write to
+ * @param str string containing the new path component
+ */
+void
+GNUNET_buffer_write_path (struct GNUNET_Buffer *buf, const char *str);
+
+
+/**
+ * Write a 0-terminated formatted string to a buffer, excluding the
+ * 0-terminator.
+ *
+ * Grows the buffer if necessary.
+ *
+ * @param buf the buffer to write to
+ * @param fmt format string
+ * @param ... format arguments
+ */
+void
+GNUNET_buffer_write_fstr (struct GNUNET_Buffer *buf, const char *fmt, ...);
+
+
+/**
+ * Write a 0-terminated formatted string to a buffer, excluding the
+ * 0-terminator.
+ *
+ * Grows the buffer if necessary.
+ *
+ * @param buf the buffer to write to
+ * @param fmt format string
+ * @param args format argument list
+ */
+void
+GNUNET_buffer_write_vfstr (struct GNUNET_Buffer *buf, const char *fmt, va_list
+ args);
+
+
+/**
+ * Clear the buffer and return the string it contained.
+ * The caller is responsible to eventually #GNUNET_free
+ * the returned string.
+ *
+ * The returned string is always 0-terminated.
+ *
+ * @param buf the buffer to reap the string from
+ * @returns the buffer contained in the string
+ */
+char *
+GNUNET_buffer_reap_str (struct GNUNET_Buffer *buf);
+
+
+/**
+ * Free the backing memory of the given buffer.
+ * Does not free the memory of the buffer control structure,
+ * which is typically stack-allocated.
+ */
+void
+GNUNET_buffer_clear (struct GNUNET_Buffer *buf);
+
+
+#endif
diff --git a/src/include/gnunet_curl_lib.h b/src/include/gnunet_curl_lib.h
index 48eb7e490..8e981e91e 100644
--- a/src/include/gnunet_curl_lib.h
+++ b/src/include/gnunet_curl_lib.h
@@ -164,7 +164,7 @@ GNUNET_CURL_perform (struct GNUNET_CURL_Context *ctx);
/**
- * Run the main event loop for the Taler interaction.
+ * Run the main event loop for the HTTP interaction.
*
* @param ctx the library context
* @param rp parses the raw response returned from
diff --git a/src/include/gnunet_gns_service.h b/src/include/gnunet_gns_service.h
index 5d2b7246a..ef81e9a88 100644
--- a/src/include/gnunet_gns_service.h
+++ b/src/include/gnunet_gns_service.h
@@ -147,6 +147,31 @@ GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
/**
+ * Perform an asynchronous lookup operation on the GNS.
+ *
+ * @param handle handle to the GNS service
+ * @param name the name to look up (in UTF-8 encoding)
+ * @param zone zone to look in
+ * @param type the GNS record type to look for
+ * @param options local options for the lookup
+ * @param recursion_depth_limit maximum number of zones
+ * that the lookup may (still) traverse
+ * @param proc function to call on result
+ * @param proc_cls closure for @a proc
+ * @return handle to the queued request
+ */
+struct GNUNET_GNS_LookupRequest *
+GNUNET_GNS_lookup_limited (struct GNUNET_GNS_Handle *handle,
+ const char *name,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *zone,
+ uint32_t type,
+ enum GNUNET_GNS_LocalOptions options,
+ uint16_t recursion_depth_limit,
+ GNUNET_GNS_LookupResultProcessor proc,
+ void *proc_cls);
+
+
+/**
* Cancel pending lookup request
*
* @param lr the lookup request to cancel
diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h
index 3a49d98b9..797c71380 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -141,6 +141,17 @@ extern "C" {
#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT 65553
/**
+ * Record type for reclaim identity attestation
+ */
+#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR 65554
+
+/**
+ * Record type for reclaim identity references
+ */
+#define GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE 65555
+
+
+/**
* Flags that can be set for a record.
*/
enum GNUNET_GNSRECORD_Flags
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index cd7cb50de..8091fb367 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2714,6 +2714,14 @@ extern "C" {
#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE 976
+#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE 977
+
+#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE 978
+
+#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT 979
+
+#define GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_STORE 980
+
/**************************************************
*
* ABD MESSAGE TYPES
@@ -3301,6 +3309,9 @@ extern "C" {
/**
* Next available: 1500
*/
+#define GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_DELETE 1500
+
+#define GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_RESULT 1501
/**
diff --git a/src/include/gnunet_reclaim_attribute_lib.h b/src/include/gnunet_reclaim_attribute_lib.h
index 4563a5f67..004f2bd10 100644
--- a/src/include/gnunet_reclaim_attribute_lib.h
+++ b/src/include/gnunet_reclaim_attribute_lib.h
@@ -50,6 +50,15 @@ extern "C" {
*/
#define GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING 1
+/**
+* No value attestation.
+*/
+#define GNUNET_RECLAIM_ATTESTATION_TYPE_NONE 10
+
+/**
+* A JSON Web Token attestation.
+*/
+#define GNUNET_RECLAIM_ATTESTATION_TYPE_JWT 11
/**
* An attribute.
@@ -67,9 +76,48 @@ struct GNUNET_RECLAIM_ATTRIBUTE_Claim
uint32_t type;
/**
+ * Flags
+ */
+ uint32_t flag;
+ /**
+ * The name of the attribute. Note "name" must never be individually
+ * free'd
+ */
+ const char *name;
+
+ /**
+ * Number of bytes in @e data.
+ */
+ size_t data_size;
+
+ /**
+ * Binary value stored as attribute value. Note: "data" must never
+ * be individually 'malloc'ed, but instead always points into some
+ * existing data area.
+ */
+ const void *data;
+};
+
+/**
+ * An attestation.
+ */
+struct GNUNET_RECLAIM_ATTESTATION_Claim
+{
+ /**
+ * ID
+ */
+ uint64_t id;
+
+ /**
+ * Type/Format of Claim
+ */
+ uint32_t type;
+
+ /**
* Version
*/
uint32_t version;
+
/**
* The name of the attribute. Note "name" must never be individually
* free'd
@@ -89,6 +137,33 @@ struct GNUNET_RECLAIM_ATTRIBUTE_Claim
const void *data;
};
+/**
+ * A reference to an Attestatiom.
+ */
+struct GNUNET_RECLAIM_ATTESTATION_REFERENCE
+{
+ /**
+ * ID
+ */
+ uint64_t id;
+
+ /**
+ * Referenced ID of Attestation
+ */
+ uint64_t id_attest;
+
+ /**
+ * The name of the attribute/attestation reference value. Note "name" must never be individually
+ * free'd
+ */
+ const char *name;
+
+ /**
+ * The name of the attribute/attestation reference value. Note "name" must never be individually
+ * free'd
+ */
+ const char *reference_value;
+};
/**
* A list of GNUNET_RECLAIM_ATTRIBUTE_Claim structures.
@@ -123,6 +198,20 @@ struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry
* The attribute claim
*/
struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
+ /**
+ * The attestation claim
+ */
+ struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
+
+ /**
+ * The reference
+ */
+ struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference;
+};
+
+struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType
+{
+ uint32_t type;
};
@@ -203,6 +292,14 @@ GNUNET_RECLAIM_ATTRIBUTE_list_serialize (
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (const char *data, size_t data_size);
+/**
+ * Count attestations in claim list
+ *
+ * @param attrs list
+ */
+int
+GNUNET_RECLAIM_ATTRIBUTE_list_count_attest (
+ const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs);
/**
* Get required size for serialization buffer
@@ -299,6 +396,154 @@ GNUNET_RECLAIM_ATTRIBUTE_value_to_string (uint32_t type,
const char *
GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (uint32_t type);
+/**
+ * Get required size for serialization buffer
+ * FIXME:
+ * 1. The naming convention is violated here.
+ * It should GNUNET_RECLAIM_ATTRIBUTE_<lowercase from here>.
+ * It might make sense to refactor attestations into a separate folder.
+ * 2. The struct should be called GNUNET_RECLAIM_ATTESTATION_Data or
+ * GNUNET_RECLAIM_ATTRIBUTE_Attestation depending on location in source.
+ *
+ * @param attr the attestation to serialize
+ * @return the required buffer size
+ */
+size_t
+GNUNET_RECLAIM_ATTESTATION_serialize_get_size (
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr);
+
+
+/**
+ * Serialize an attestation
+ *
+ * @param attr the attestation to serialize
+ * @param result the serialized attestation
+ * @return length of serialized data
+ */
+size_t
+GNUNET_RECLAIM_ATTESTATION_serialize (
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr,
+ char *result);
+
+
+/**
+ * Deserialize an attestation
+ *
+ * @param data the serialized attestation
+ * @param data_size the length of the serialized data
+ *
+ * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
+ */
+struct GNUNET_RECLAIM_ATTESTATION_Claim *
+GNUNET_RECLAIM_ATTESTATION_deserialize (const char *data, size_t data_size);
+
+
+/**
+ * Create a new attestation.
+ *
+ * @param attr_name the attestation name
+ * @param type the attestation type
+ * @param data the attestation value
+ * @param data_size the attestation value size
+ * @return the new attestation
+ */
+struct GNUNET_RECLAIM_ATTESTATION_Claim *
+GNUNET_RECLAIM_ATTESTATION_claim_new (const char *attr_name,
+ uint32_t type,
+ const void *data,
+ size_t data_size);
+
+/**
+ * Convert the 'claim' of an attestation to a string
+ *
+ * @param type the type of attestation
+ * @param data claim in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the claim
+ */
+char *
+GNUNET_RECLAIM_ATTESTATION_value_to_string (uint32_t type,
+ const void *data,
+ size_t data_size);
+
+/**
+ * Convert human-readable version of a 'claim' of an attestation to the binary
+ * representation
+ *
+ * @param type type of the claim
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_RECLAIM_ATTESTATION_string_to_value (uint32_t type,
+ const char *s,
+ void **data,
+ size_t *data_size);
+
+/**
+ * Convert an attestation type number to the corresponding attestation type string
+ *
+ * @param type number of a type
+ * @return corresponding typestring, NULL on error
+ */
+const char *
+GNUNET_RECLAIM_ATTESTATION_number_to_typename (uint32_t type);
+
+/**
+ * Convert an attestation type name to the corresponding number
+ *
+ * @param typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+uint32_t
+GNUNET_RECLAIM_ATTESTATION_typename_to_number (const char *typename);
+
+/**
+ * Create a new attestation reference.
+ *
+ * @param attr_name the referenced claim name
+ * @param ref_value the claim name in the attestation
+ * @return the new reference
+ */
+struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *
+GNUNET_RECLAIM_ATTESTATION_reference_new (const char *attr_name,
+ const char *ref_value);
+
+
+/**
+ * Get required size for serialization buffer
+ *
+ * @param attr the reference to serialize
+ * @return the required buffer size
+ */
+size_t
+GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr);
+
+/**
+ * Serialize a reference
+ *
+ * @param attr the reference to serialize
+ * @param result the serialized reference
+ * @return length of serialized data
+ */
+size_t
+GNUNET_RECLAIM_ATTESTATION_REF_serialize (
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr,
+ char *result);
+
+/**
+ * Deserialize a reference
+ *
+ * @param data the serialized reference
+ * @param data_size the length of the serialized data
+ *
+ * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
+ */
+struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *
+GNUNET_RECLAIM_ATTESTATION_REF_deserialize (const char *data, size_t data_size);
#if 0 /* keep Emacsens' auto-indent happy */
{
diff --git a/src/include/gnunet_reclaim_attribute_plugin.h b/src/include/gnunet_reclaim_attribute_plugin.h
index 26a4bb4f2..e61cca5b2 100644
--- a/src/include/gnunet_reclaim_attribute_plugin.h
+++ b/src/include/gnunet_reclaim_attribute_plugin.h
@@ -134,6 +134,33 @@ struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions
* Number to typename.
*/
GNUNET_RECLAIM_ATTRIBUTE_NumberToTypenameFunction number_to_typename;
+
+ /**
+ * FIXME: It is odd that attestation functions are withing the attribute
+ * plugin. An attribute type may be backed by an attestation, but not
+ * necessarily.
+ * Maybe it would make more sense to refactor this into an attestation
+ * plugin?
+ *
+ * Attestation Conversion to string.
+ */
+ GNUNET_RECLAIM_ATTRIBUTE_ValueToStringFunction value_to_string_attest;
+
+ /**
+ * Attestation Conversion to binary.
+ */
+ GNUNET_RECLAIM_ATTRIBUTE_StringToValueFunction string_to_value_attest;
+
+ /**
+ * Attestation Typename to number.
+ */
+ GNUNET_RECLAIM_ATTRIBUTE_TypenameToNumberFunction typename_to_number_attest;
+
+ /**
+ * Attestation Number to typename.
+ */
+ GNUNET_RECLAIM_ATTRIBUTE_NumberToTypenameFunction number_to_typename_attest;
+
};
diff --git a/src/include/gnunet_reclaim_service.h b/src/include/gnunet_reclaim_service.h
index 237d791d9..214cdba69 100644
--- a/src/include/gnunet_reclaim_service.h
+++ b/src/include/gnunet_reclaim_service.h
@@ -117,7 +117,9 @@ typedef void (*GNUNET_RECLAIM_ContinuationWithStatus) (void *cls,
*/
typedef void (*GNUNET_RECLAIM_AttributeResult) (
void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
- const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr);
+ const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference);
/**
@@ -152,6 +154,28 @@ GNUNET_RECLAIM_attribute_store (
/**
+ * Store an attestation. If the attestation is already present,
+ * it is replaced with the new attestation.
+ *
+ * @param h handle to the re:claimID service
+ * @param pkey private key of the identity
+ * @param attr the attestation value
+ * @param exp_interval the relative expiration interval for the attestation
+ * @param cont continuation to call when done
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the request
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_attestation_store (
+ struct GNUNET_RECLAIM_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr,
+ const struct GNUNET_TIME_Relative *exp_interval,
+ GNUNET_RECLAIM_ContinuationWithStatus cont,
+ void *cont_cls);
+
+
+/**
* Delete an attribute. Tickets used to share this attribute are updated
* accordingly.
*
@@ -169,8 +193,44 @@ GNUNET_RECLAIM_attribute_delete (
const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
GNUNET_RECLAIM_ContinuationWithStatus cont, void *cont_cls);
+/**
+ * Delete an attestation. Tickets used to share this attestation are updated
+ * accordingly.
+ *
+ * @param h handle to the re:claimID service
+ * @param pkey Private key of the identity to add an attribute to
+ * @param attr The attestation
+ * @param cont Continuation to call when done
+ * @param cont_cls Closure for @a cont
+ * @return handle Used to to abort the request
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_attestation_delete (
+ struct GNUNET_RECLAIM_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr,
+ GNUNET_RECLAIM_ContinuationWithStatus cont,
+ void *cont_cls);
/**
+ * Delete an attestation reference. Tickets used to share this reference are updated
+ * accordingly.
+ *
+ * @param h handle to the re:claimID service
+ * @param pkey Private key of the identity to delete the reference from
+ * @param attr The reference
+ * @param cont Continuation to call when done
+ * @param cont_cls Closure for @a cont
+ * @return handle Used to to abort the request
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_attestation_reference_delete (
+ struct GNUNET_RECLAIM_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr,
+ GNUNET_RECLAIM_ContinuationWithStatus cont,
+ void *cont_cls);
+/**
* List all attributes for a local identity.
* This MUST lock the `struct GNUNET_RECLAIM_Handle`
* for any other calls than #GNUNET_RECLAIM_get_attributes_next() and
@@ -202,6 +262,26 @@ GNUNET_RECLAIM_get_attributes_start (
GNUNET_RECLAIM_AttributeResult proc, void *proc_cls,
GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls);
+/**
+ * Store an attestation reference. If the reference is already present,
+ * it is replaced with the new reference.
+ *
+ * @param h handle to the re:claimID service
+ * @param pkey private key of the identity
+ * @param attr the reference value
+ * @param exp_interval the relative expiration interval for the reference
+ * @param cont continuation to call when done
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the request
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_attestation_reference_store (
+ struct GNUNET_RECLAIM_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr,
+ const struct GNUNET_TIME_Relative *exp_interval,
+ GNUNET_RECLAIM_ContinuationWithStatus cont,
+ void *cont_cls);
/**
* Calls the record processor specified in #GNUNET_RECLAIM_get_attributes_start
diff --git a/src/include/gnunet_util_taler_wallet_lib.h b/src/include/gnunet_util_taler_wallet_lib.h
deleted file mode 100644
index a036824f6..000000000
--- a/src/include/gnunet_util_taler_wallet_lib.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- This file is part of GNUnet
- Copyright (C) 2009, 2015 GNUnet e.V.
-
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- SPDX-License-Identifier: AGPL3.0-or-later
- */
-
-/**
- * @author Christian Grothoff
- *
- * @file
- * Convenience header including all headers of subsystems in
- * gnunet_util_taler_wallet library. Note that (due to the structure of the
- * original headers), not all symbols declared by the included headers are
- * actually included in the gnunet_util_taler_wallet library! The library
- * excludes anything relating to the GNUnet installation location, scheduler,
- * networking or OS-specific logic that would not apply to Apps/Browser
- * extensions.
- */
-
-#ifndef GNUNET_UTIL_TALER_WALLET_LIB_H
-#define GNUNET_UTIL_TALER_WALLET_LIB_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0 /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "gnunet_crypto_lib.h"
-#include "gnunet_container_lib.h"
-#include "gnunet_strings_lib.h"
-
-#if 0 /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c b/src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c
index bb60909d9..ade2a27bb 100644
--- a/src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c
+++ b/src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c
@@ -90,6 +90,63 @@ gnuid_string_to_value (void *cls,
}
}
+/**
+ * Convert the 'value' of an attestation to a string.
+ *
+ * @param cls closure, unused
+ * @param type type of the attestation
+ * @param data value in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the value
+ */
+static char *
+gnuid_value_to_string_attest (void *cls,
+ uint32_t type,
+ const void *data,
+ size_t data_size)
+{
+ switch (type)
+ {
+ case GNUNET_RECLAIM_ATTESTATION_TYPE_JWT:
+ return GNUNET_strndup (data, data_size);
+
+ default:
+ return NULL;
+ }
+}
+
+
+/**
+ * Convert human-readable version of a 'value' of an attestation to the binary
+ * representation.
+ *
+ * @param cls closure, unused
+ * @param type type of the attestation
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+static int
+gnuid_string_to_value_attest (void *cls,
+ uint32_t type,
+ const char *s,
+ void **data,
+ size_t *data_size)
+{
+ if (NULL == s)
+ return GNUNET_SYSERR;
+ switch (type)
+ {
+ case GNUNET_RECLAIM_ATTESTATION_TYPE_JWT:
+ *data = GNUNET_strdup (s);
+ *data_size = strlen (s);
+ return GNUNET_OK;
+
+ default:
+ return GNUNET_SYSERR;
+ }
+}
/**
* Mapping of attribute type numbers to human-readable
@@ -102,6 +159,16 @@ static struct
} gnuid_name_map[] = { { "STRING", GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING },
{ NULL, UINT32_MAX } };
+/**
+ * Mapping of attestation type numbers to human-readable
+ * attestation type names.
+ */
+static struct
+{
+ const char *name;
+ uint32_t number;
+} gnuid_attest_name_map[] = { { "JWT", GNUNET_RECLAIM_ATTESTATION_TYPE_JWT },
+ { NULL, UINT32_MAX } };
/**
* Convert a type name to the corresponding number.
@@ -141,6 +208,44 @@ gnuid_number_to_typename (void *cls, uint32_t type)
return gnuid_name_map[i].name;
}
+/**
+ * Convert a type name to the corresponding number.
+ *
+ * @param cls closure, unused
+ * @param gnuid_typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+static uint32_t
+gnuid_typename_to_number_attest (void *cls, const char *gnuid_typename)
+{
+ unsigned int i;
+
+ i = 0;
+ while ((NULL != gnuid_attest_name_map[i].name) &&
+ (0 != strcasecmp (gnuid_typename, gnuid_attest_name_map[i].name)))
+ i++;
+ return gnuid_attest_name_map[i].number;
+}
+
+/**
+ * Convert a type number (i.e. 1) to the corresponding type string
+ *
+ * @param cls closure, unused
+ * @param type number of a type to convert
+ * @return corresponding typestring, NULL on error
+ */
+static const char *
+gnuid_number_to_typename_attest (void *cls, uint32_t type)
+{
+ unsigned int i;
+
+ i = 0;
+ while ((NULL != gnuid_attest_name_map[i].name) && (type !=
+ gnuid_attest_name_map[i].
+ number))
+ i++;
+ return gnuid_attest_name_map[i].name;
+}
/**
* Entry point for the plugin.
@@ -158,6 +263,10 @@ libgnunet_plugin_reclaim_attribute_gnuid_init (void *cls)
api->string_to_value = &gnuid_string_to_value;
api->typename_to_number = &gnuid_typename_to_number;
api->number_to_typename = &gnuid_number_to_typename;
+ api->value_to_string_attest = &gnuid_value_to_string_attest;
+ api->string_to_value_attest = &gnuid_string_to_value_attest;
+ api->typename_to_number_attest = &gnuid_typename_to_number_attest;
+ api->number_to_typename_attest = &gnuid_number_to_typename_attest;
return api;
}
diff --git a/src/reclaim-attribute/reclaim_attribute.c b/src/reclaim-attribute/reclaim_attribute.c
index b81394ad2..43199c108 100644
--- a/src/reclaim-attribute/reclaim_attribute.c
+++ b/src/reclaim-attribute/reclaim_attribute.c
@@ -217,6 +217,116 @@ GNUNET_RECLAIM_ATTRIBUTE_value_to_string (uint32_t type,
return NULL;
}
+/**
+ * Convert an attestation type name to the corresponding number
+ *
+ * @param typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+uint32_t
+GNUNET_RECLAIM_ATTESTATION_typename_to_number (const char *typename)
+{
+ unsigned int i;
+ struct Plugin *plugin;
+ uint32_t ret;
+ init ();
+ for (i = 0; i < num_plugins; i++)
+ {
+ plugin = attr_plugins[i];
+ if (UINT32_MAX !=
+ (ret = plugin->api->typename_to_number_attest (plugin->api->cls,
+ typename)))
+ return ret;
+ }
+ return UINT32_MAX;
+}
+
+/**
+ * Convert an attestation type number to the corresponding attestation type string
+ *
+ * @param type number of a type
+ * @return corresponding typestring, NULL on error
+ */
+const char *
+GNUNET_RECLAIM_ATTESTATION_number_to_typename (uint32_t type)
+{
+ unsigned int i;
+ struct Plugin *plugin;
+ const char *ret;
+
+ init ();
+ for (i = 0; i < num_plugins; i++)
+ {
+ plugin = attr_plugins[i];
+ if (NULL !=
+ (ret = plugin->api->number_to_typename_attest (plugin->api->cls, type)))
+ return ret;
+ }
+ return NULL;
+}
+/**
+ * Convert human-readable version of a 'claim' of an attestation to the binary
+ * representation
+ *
+ * @param type type of the claim
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_RECLAIM_ATTESTATION_string_to_value (uint32_t type,
+ const char *s,
+ void **data,
+ size_t *data_size)
+{
+ unsigned int i;
+ struct Plugin *plugin;
+
+ init ();
+ for (i = 0; i < num_plugins; i++)
+ {
+ plugin = attr_plugins[i];
+ if (GNUNET_OK == plugin->api->string_to_value_attest (plugin->api->cls,
+ type,
+ s,
+ data,
+ data_size))
+ return GNUNET_OK;
+ }
+ return GNUNET_SYSERR;
+}
+
+
+/**
+ * Convert the 'claim' of an attestation to a string
+ *
+ * @param type the type of attestation
+ * @param data claim in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the claim
+ */
+char *
+GNUNET_RECLAIM_ATTESTATION_value_to_string (uint32_t type,
+ const void *data,
+ size_t data_size)
+{
+ unsigned int i;
+ struct Plugin *plugin;
+ char *ret;
+
+ init ();
+ for (i = 0; i < num_plugins; i++)
+ {
+ plugin = attr_plugins[i];
+ if (NULL != (ret = plugin->api->value_to_string_attest (plugin->api->cls,
+ type,
+ data,
+ data_size)))
+ return ret;
+ }
+ return NULL;
+}
/**
* Create a new attribute.
@@ -243,6 +353,42 @@ GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char *attr_name,
+ strlen (attr_name_tmp) + 1 + data_size);
attr->type = type;
attr->data_size = data_size;
+ attr->flag = 0;
+ write_ptr = (char *) &attr[1];
+ GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
+ attr->name = write_ptr;
+ write_ptr += strlen (attr->name) + 1;
+ GNUNET_memcpy (write_ptr, data, data_size);
+ attr->data = write_ptr;
+ GNUNET_free (attr_name_tmp);
+ return attr;
+}
+
+/**
+ * Create a new attestation.
+ *
+ * @param attr_name the attestation name
+ * @param type the attestation type
+ * @param data the attestation value
+ * @param data_size the attestation value size
+ * @return the new attestation
+ */
+struct GNUNET_RECLAIM_ATTESTATION_Claim *
+GNUNET_RECLAIM_ATTESTATION_claim_new (const char *attr_name,
+ uint32_t type,
+ const void *data,
+ size_t data_size)
+{
+ struct GNUNET_RECLAIM_ATTESTATION_Claim *attr;
+ char *write_ptr;
+ char *attr_name_tmp = GNUNET_strdup (attr_name);
+
+ GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
+
+ attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim)
+ + strlen (attr_name_tmp) + 1 + data_size);
+ attr->type = type;
+ attr->data_size = data_size;
attr->version = 0;
write_ptr = (char *) &attr[1];
GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
@@ -254,6 +400,40 @@ GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char *attr_name,
return attr;
}
+/**
+ * Create a new attestation reference.
+ *
+ * @param attr_name the referenced claim name
+ * @param ref_value the claim name in the attestation
+ * @return the new reference
+ */
+struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *
+GNUNET_RECLAIM_ATTESTATION_reference_new (const char *attr_name,
+ const char *ref_value)
+{
+ struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
+ char *write_ptr;
+ char *attr_name_tmp = GNUNET_strdup (attr_name);
+ char *ref_value_tmp = GNUNET_strdup (ref_value);
+
+ GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
+ GNUNET_STRINGS_utf8_tolower (ref_value, ref_value_tmp);
+
+ attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_REFERENCE)
+ + strlen (attr_name_tmp) + strlen (ref_value_tmp) + 2);
+
+ write_ptr = (char *) &attr[1];
+ GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
+ attr->name = write_ptr;
+
+ write_ptr += strlen (attr_name) + 1;
+ GNUNET_memcpy (write_ptr, ref_value_tmp, strlen (ref_value_tmp) + 1);
+ attr->reference_value = write_ptr;
+
+ GNUNET_free (attr_name_tmp);
+ GNUNET_free (ref_value_tmp);
+ return attr;
+}
/**
* Add a new attribute to a claim list
@@ -296,7 +476,30 @@ GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (
size_t len = 0;
for (le = attrs->list_head; NULL != le; le = le->next)
- len += GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
+ {
+ if (NULL != le->claim)
+ {
+ len += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
+ len += GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
+ }
+ else if (NULL != le->attest )
+ {
+ len += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
+ len += GNUNET_RECLAIM_ATTESTATION_serialize_get_size (le->attest);
+ }
+ else if (NULL != le->reference)
+ {
+ len += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
+ len += GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (le->reference);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unserialized Claim List Entry Type for size not known.\n");
+ break;
+ }
+ len += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+ }
return len;
}
@@ -317,14 +520,50 @@ GNUNET_RECLAIM_ATTRIBUTE_list_serialize (
size_t len;
size_t total_len;
char *write_ptr;
-
write_ptr = result;
total_len = 0;
for (le = attrs->list_head; NULL != le; le = le->next)
{
- len = GNUNET_RECLAIM_ATTRIBUTE_serialize (le->claim, write_ptr);
- total_len += len;
- write_ptr += len;
+ struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType *list_type;
+ if (NULL != le->claim)
+ {
+ list_type = (struct
+ GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType *) write_ptr;
+ list_type->type = htons (1);
+ total_len += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
+ write_ptr += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
+ len = GNUNET_RECLAIM_ATTRIBUTE_serialize (le->claim, write_ptr);
+ total_len += len;
+ write_ptr += len;
+ }
+ else if (NULL != le->attest )
+ {
+ list_type = (struct
+ GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType *) write_ptr;
+ list_type->type = htons (2);
+ total_len += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
+ write_ptr += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
+ len = GNUNET_RECLAIM_ATTESTATION_serialize (le->attest, write_ptr);
+ total_len += len;
+ write_ptr += len;
+ }
+ else if (NULL != le->reference)
+ {
+ list_type = (struct
+ GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType *) write_ptr;
+ list_type->type = htons (3);
+ total_len += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
+ write_ptr += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
+ len = GNUNET_RECLAIM_ATTESTATION_REF_serialize (le->reference, write_ptr);
+ total_len += len;
+ write_ptr += len;
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unserialized Claim List Entry Type not known.\n");
+ continue;
+ }
}
return total_len;
}
@@ -345,23 +584,75 @@ GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (const char *data, size_t data_size)
size_t attr_len;
const char *read_ptr;
- if (data_size < sizeof(struct Attribute))
+ if ((data_size < sizeof(struct Attribute) + sizeof(struct
+ GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry))
+ && (data_size < sizeof(struct
+ Attestation)
+ + sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry)) &&
+ (data_size < sizeof(struct Attestation_Reference) + sizeof(struct
+ GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry)) )
return NULL;
attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
read_ptr = data;
while (((data + data_size) - read_ptr) >= sizeof(struct Attribute))
{
- le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
- le->claim =
- GNUNET_RECLAIM_ATTRIBUTE_deserialize (read_ptr,
- data_size - (read_ptr - data));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Deserialized attribute %s\n",
- le->claim->name);
- GNUNET_CONTAINER_DLL_insert (attrs->list_head, attrs->list_tail, le);
- attr_len = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
- read_ptr += attr_len;
+ struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType *list_type;
+ list_type = (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType *) read_ptr;
+ if (1 == ntohs (list_type->type))
+ {
+ le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+ read_ptr += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
+ if (((data + data_size) - read_ptr) < sizeof(struct Attribute))
+ break;
+ le->attest = NULL;
+ le->reference = NULL;
+ le->claim =
+ GNUNET_RECLAIM_ATTRIBUTE_deserialize (read_ptr,
+ data_size - (read_ptr - data));
+ GNUNET_CONTAINER_DLL_insert (attrs->list_head, attrs->list_tail, le);
+ attr_len = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
+ read_ptr += attr_len;
+ }
+ else if (2 == ntohs (list_type->type))
+ {
+ le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+ read_ptr += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
+ if (((data + data_size) - read_ptr) < sizeof(struct Attestation))
+ break;
+ le->claim = NULL;
+ le->reference = NULL;
+ le->attest =
+ GNUNET_RECLAIM_ATTESTATION_deserialize (read_ptr,
+ data_size - (read_ptr - data));
+ GNUNET_CONTAINER_DLL_insert (attrs->list_head, attrs->list_tail, le);
+ attr_len = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (le->attest);
+ read_ptr += attr_len;
+ }
+ else if (3 == ntohs (list_type->type))
+ {
+ le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+ read_ptr += sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntryType);
+ if (((data + data_size) - read_ptr) < sizeof(struct
+ Attestation_Reference))
+ break;
+ le->claim = NULL;
+ le->attest = NULL;
+ le->reference =
+ GNUNET_RECLAIM_ATTESTATION_REF_deserialize (read_ptr,
+ data_size - (read_ptr
+ - data));
+ GNUNET_CONTAINER_DLL_insert (attrs->list_head, attrs->list_tail, le);
+ attr_len = GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (
+ le->reference);
+ read_ptr += attr_len;
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Serialized Claim List Entry Type not known.\n");
+ break;
+ }
}
return attrs;
}
@@ -381,16 +672,45 @@ GNUNET_RECLAIM_ATTRIBUTE_list_dup (
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *result;
result = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
+ if (NULL == attrs->list_head)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Duplicating empty List\n");
+ }
for (le = attrs->list_head; NULL != le; le = le->next)
{
result_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
- result_le->claim =
- GNUNET_RECLAIM_ATTRIBUTE_claim_new (le->claim->name,
- le->claim->type,
- le->claim->data,
- le->claim->data_size);
- result_le->claim->version = le->claim->version;
- result_le->claim->id = le->claim->id;
+ result_le->claim = NULL;
+ result_le->attest = NULL;
+ result_le->reference = NULL;
+ if (NULL != le->claim)
+ {
+ result_le->claim =
+ GNUNET_RECLAIM_ATTRIBUTE_claim_new (le->claim->name,
+ le->claim->type,
+ le->claim->data,
+ le->claim->data_size);
+
+ result_le->claim->id = le->claim->id;
+ result_le->claim->flag = le->claim->flag;
+ }
+ if ( NULL != le->attest)
+ {
+ result_le->attest = GNUNET_RECLAIM_ATTESTATION_claim_new (
+ le->attest->name,
+ le->attest->type,
+ le->attest->data,
+ le->attest->
+ data_size);
+ result_le->attest->id = le->attest->id;
+ }
+ if (NULL !=le->reference)
+ {
+ result_le->reference = GNUNET_RECLAIM_ATTESTATION_reference_new (
+ le->reference->name,
+ le->reference->reference_value);
+ result_le->reference->id = le->reference->id;
+ result_le->reference->id_attest = le->reference->id_attest;
+ }
GNUNET_CONTAINER_DLL_insert (result->list_head,
result->list_tail,
result_le);
@@ -411,9 +731,14 @@ GNUNET_RECLAIM_ATTRIBUTE_list_destroy (
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *tmp_le;
- for (le = attrs->list_head; NULL != le;)
+ for (le = attrs->list_head; NULL != le; le = le->next)
{
- GNUNET_free (le->claim);
+ if (NULL != le->claim)
+ GNUNET_free (le->claim);
+ if (NULL != le->attest)
+ GNUNET_free (le->attest);
+ if (NULL != le->reference)
+ GNUNET_free (le->reference);
tmp_le = le;
le = le->next;
GNUNET_free (tmp_le);
@@ -421,7 +746,24 @@ GNUNET_RECLAIM_ATTRIBUTE_list_destroy (
GNUNET_free (attrs);
}
-
+/**
+ * Count attestations in claim list
+ *
+ * @param attrs list
+ */
+int
+GNUNET_RECLAIM_ATTRIBUTE_list_count_attest (
+ const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
+{
+ struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+ int i = 0;
+ for (le = attrs->list_head; NULL != le; le = le->next)
+ {
+ if (NULL != le->attest)
+ i++;
+ }
+ return i;
+}
/**
* Get required size for serialization buffer
*
@@ -455,7 +797,7 @@ GNUNET_RECLAIM_ATTRIBUTE_serialize (
attr_ser = (struct Attribute *) result;
attr_ser->attribute_type = htons (attr->type);
- attr_ser->attribute_version = htonl (attr->version);
+ attr_ser->attribute_version = htonl (attr->flag);
attr_ser->attribute_id = GNUNET_htonll (attr->id);
name_len = strlen (attr->name);
attr_ser->name_len = htons (name_len);
@@ -505,7 +847,7 @@ GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char *data, size_t data_size)
attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_Claim)
+ data_len + name_len + 1);
attr->type = ntohs (attr_ser->attribute_type);
- attr->version = ntohl (attr_ser->attribute_version);
+ attr->flag = ntohl (attr_ser->attribute_version);
attr->id = GNUNET_ntohll (attr_ser->attribute_id);
attr->data_size = data_len;
@@ -521,4 +863,193 @@ GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char *data, size_t data_size)
}
+/**
+ * Get required size for serialization buffer
+ *
+ * @param attr the attestation to serialize
+ * @return the required buffer size
+ */
+size_t
+GNUNET_RECLAIM_ATTESTATION_serialize_get_size (
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr)
+{
+ return sizeof(struct Attestation) + strlen (attr->name) + attr->data_size;
+}
+
+/**
+ * Serialize an attestation
+ *
+ * @param attr the attestation to serialize
+ * @param result the serialized attestation
+ * @return length of serialized data
+ */
+size_t
+GNUNET_RECLAIM_ATTESTATION_serialize (
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr,
+ char *result)
+{
+ size_t data_len_ser;
+ size_t name_len;
+ struct Attestation *attr_ser;
+ char *write_ptr;
+
+ attr_ser = (struct Attestation *) result;
+ attr_ser->attestation_type = htons (attr->type);
+ attr_ser->attestation_version = htonl (attr->version);
+ attr_ser->attestation_id = GNUNET_htonll (attr->id);
+ name_len = strlen (attr->name);
+ attr_ser->name_len = htons (name_len);
+ write_ptr = (char *) &attr_ser[1];
+ GNUNET_memcpy (write_ptr, attr->name, name_len);
+ write_ptr += name_len;
+ // TODO plugin-ize
+ // data_len_ser = plugin->serialize_attribute_value (attr,
+ // &attr_ser[1]);
+ data_len_ser = attr->data_size;
+ GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
+ attr_ser->data_size = htons (data_len_ser);
+
+ return sizeof(struct Attestation) + strlen (attr->name) + attr->data_size;
+}
+
+/**
+ * Deserialize an attestation
+ *
+ * @param data the serialized attestation
+ * @param data_size the length of the serialized data
+ *
+ * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
+ */
+struct GNUNET_RECLAIM_ATTESTATION_Claim *
+GNUNET_RECLAIM_ATTESTATION_deserialize (const char *data, size_t data_size)
+{
+ struct GNUNET_RECLAIM_ATTESTATION_Claim *attr;
+ struct Attestation *attr_ser;
+ size_t data_len;
+ size_t name_len;
+ char *write_ptr;
+
+ if (data_size < sizeof(struct Attestation))
+ return NULL;
+
+ attr_ser = (struct Attestation *) data;
+ data_len = ntohs (attr_ser->data_size);
+ name_len = ntohs (attr_ser->name_len);
+ if (data_size < sizeof(struct Attestation) + data_len + name_len)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Buffer too small to deserialize\n");
+ return NULL;
+ }
+ attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim)
+ + data_len + name_len + 1);
+ attr->type = ntohs (attr_ser->attestation_type);
+ attr->version = ntohl (attr_ser->attestation_version);
+ attr->id = GNUNET_ntohll (attr_ser->attestation_id);
+ attr->data_size = data_len;
+
+ write_ptr = (char *) &attr[1];
+ GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
+ write_ptr[name_len] = '\0';
+ attr->name = write_ptr;
+
+ write_ptr += name_len + 1;
+ GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, attr->data_size);
+ attr->data = write_ptr;
+ return attr;
+}
+
+/**
+ * Get required size for serialization buffer
+ *
+ * @param attr the reference to serialize
+ * @return the required buffer size
+ */
+size_t
+GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr)
+{
+ return sizeof(struct Attestation_Reference) + strlen (attr->name) + strlen (
+ attr->reference_value);
+}
+
+
+/**
+ * Serialize a reference
+ *
+ * @param attr the reference to serialize
+ * @param result the serialized reference
+ * @return length of serialized data
+ */
+size_t
+GNUNET_RECLAIM_ATTESTATION_REF_serialize (
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr,
+ char *result)
+{
+ size_t name_len;
+ size_t refval_len;
+ struct Attestation_Reference *attr_ser;
+ char *write_ptr;
+ attr_ser = (struct Attestation_Reference *) result;
+ attr_ser->reference_id = GNUNET_htonll (attr->id);
+ attr_ser->attestation_id = GNUNET_htonll (attr->id_attest);
+ name_len = strlen (attr->name);
+ refval_len = strlen (attr->reference_value);
+ attr_ser->name_len = htons (name_len);
+ attr_ser->ref_value_len = htons (refval_len);
+ write_ptr = (char *) &attr_ser[1];
+ GNUNET_memcpy (write_ptr, attr->name, name_len);
+ write_ptr += name_len;
+ GNUNET_memcpy (write_ptr, attr->reference_value, refval_len);
+
+ return sizeof(struct Attestation_Reference) + strlen (attr->name) + strlen (
+ attr->reference_value);
+}
+
+
+/**
+ * Deserialize a reference
+ *
+ * @param data the serialized reference
+ * @param data_size the length of the serialized data
+ *
+ * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
+ */
+struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *
+GNUNET_RECLAIM_ATTESTATION_REF_deserialize (const char *data, size_t data_size)
+{
+ struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
+ struct Attestation_Reference *attr_ser;
+ size_t name_len;
+ size_t refval_len;
+ char *write_ptr;
+
+ if (data_size < sizeof(struct Attestation_Reference))
+ return NULL;
+ attr_ser = (struct Attestation_Reference *) data;
+ name_len = ntohs (attr_ser->name_len);
+ refval_len = ntohs (attr_ser->ref_value_len);
+ if (data_size < sizeof(struct Attestation_Reference) + refval_len + name_len)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Buffer too small to deserialize\n");
+ return NULL;
+ }
+ attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_REFERENCE)
+ + refval_len + name_len + 2);
+
+ attr->id = GNUNET_ntohll (attr_ser->reference_id);
+ attr->id_attest = GNUNET_ntohll (attr_ser->attestation_id);
+
+ write_ptr = (char *) &attr[1];
+ GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
+ write_ptr[name_len] = '\0';
+ attr->name = write_ptr;
+
+ write_ptr += name_len + 1;
+ GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, refval_len);
+ write_ptr[refval_len] = '\0';
+ attr->reference_value = write_ptr;
+ return attr;
+}
/* end of reclaim_attribute.c */
diff --git a/src/reclaim-attribute/reclaim_attribute.h b/src/reclaim-attribute/reclaim_attribute.h
index d7358847e..80f1e5aac 100644
--- a/src/reclaim-attribute/reclaim_attribute.h
+++ b/src/reclaim-attribute/reclaim_attribute.h
@@ -61,4 +61,66 @@ struct Attribute
// followed by data_size Attribute value data
};
+/**
+ * Serialized attestation claim
+ */
+struct Attestation
+{
+ /**
+ * Attestation type
+ */
+ uint32_t attestation_type;
+
+ /**
+ * Attestation version
+ */
+ uint32_t attestation_version;
+
+ /**
+ * Attestation ID
+ */
+ uint64_t attestation_id;
+
+ /**
+ * Name length
+ */
+ uint32_t name_len;
+
+ /**
+ * Data size
+ */
+ uint32_t data_size;
+
+ // followed by data_size Attestation value data
+};
+
+/**
+ * Serialized attestation reference
+ */
+struct Attestation_Reference
+{
+ /**
+ * Reference ID
+ */
+ uint64_t reference_id;
+
+ /**
+ * The ID of the referenced attestation
+ */
+ uint64_t attestation_id;
+
+ /**
+ * Claim Name length
+ */
+ uint32_t name_len;
+
+ /**
+ * Length of the referenced value
+ */
+ uint32_t ref_value_len;
+
+
+ // followed by the name and referenced value
+};
+
#endif
diff --git a/src/reclaim/gnunet-reclaim.c b/src/reclaim/gnunet-reclaim.c
index 58f8cd6e2..5f9170f05 100644
--- a/src/reclaim/gnunet-reclaim.c
+++ b/src/reclaim/gnunet-reclaim.c
@@ -226,7 +226,9 @@ store_attr_cont (void *cls, int32_t success, const char *emsg)
static void
process_attrs (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
- const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+ const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
{
char *value_str;
char *id;
@@ -253,7 +255,7 @@ process_attrs (void *cls,
attr->name,
value_str,
attr_type,
- attr->version,
+ attr->flag,
id);
GNUNET_free (id);
}
@@ -445,7 +447,9 @@ iter_finished (void *cls)
static void
iter_cb (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
- const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+ const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
{
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
char *attrs_tmp;
@@ -480,7 +484,7 @@ iter_cb (void *cls,
attr->type,
attr->data,
attr->data_size);
- le->claim->version = attr->version;
+ le->claim->flag = attr->flag;
le->claim->id = attr->id;
GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
attr_list->list_tail,
@@ -514,7 +518,7 @@ iter_cb (void *cls,
attr->name,
attr_str,
attr_type,
- attr->version,
+ attr->flag,
id);
GNUNET_free (id);
}
diff --git a/src/reclaim/gnunet-service-reclaim.c b/src/reclaim/gnunet-service-reclaim.c
index a83ea05a6..556006af0 100644
--- a/src/reclaim/gnunet-service-reclaim.c
+++ b/src/reclaim/gnunet-service-reclaim.c
@@ -266,6 +266,15 @@ struct AttributeDeleteHandle
struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
/**
+ * The attestation to delete
+ */
+ struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
+
+ /**
+ * The reference to delete
+ */
+ struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference;
+ /**
* Tickets to update
*/
struct TicketRecordsEntry *tickets_to_update_head;
@@ -328,6 +337,16 @@ struct AttributeStoreHandle
struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
/**
+ * The attestation to store
+ */
+ struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
+
+ /**
+ * The reference to store
+ */
+ struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference;
+
+ /**
* The attribute expiration interval
*/
struct GNUNET_TIME_Relative exp;
@@ -459,6 +478,10 @@ cleanup_adh (struct AttributeDeleteHandle *adh)
GNUNET_free (adh->label);
if (NULL != adh->claim)
GNUNET_free (adh->claim);
+ if (NULL != adh->attest)
+ GNUNET_free (adh->attest);
+ if (NULL != adh->reference)
+ GNUNET_free (adh->reference);
while (NULL != (le = adh->tickets_to_update_head))
{
GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
@@ -486,6 +509,10 @@ cleanup_as_handle (struct AttributeStoreHandle *ash)
GNUNET_NAMESTORE_cancel (ash->ns_qe);
if (NULL != ash->claim)
GNUNET_free (ash->claim);
+ if (NULL != ash->attest)
+ GNUNET_free (ash->attest);
+ if (NULL != ash->reference)
+ GNUNET_free (ash->reference);
GNUNET_free (ash);
}
@@ -1023,6 +1050,478 @@ handle_attribute_store_message (void *cls,
/**
+ * Attestation store result handler
+ *
+ * @param cls our attribute store handle
+ * @param success GNUNET_OK if successful
+ * @param emsg error message (NULL if success=GNUNET_OK)
+ */
+static void
+attest_store_cont (void *cls, int32_t success, const char *emsg)
+{
+ struct AttributeStoreHandle *ash = cls;
+ struct GNUNET_MQ_Envelope *env;
+ struct SuccessResultMessage *acr_msg;
+
+ ash->ns_qe = NULL;
+ GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
+ ash->client->store_op_tail,
+ ash);
+
+ if (GNUNET_SYSERR == success)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to store attestation %s\n",
+ emsg);
+ cleanup_as_handle (ash);
+ GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
+ env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
+ acr_msg->id = htonl (ash->r_id);
+ acr_msg->op_result = htonl (GNUNET_OK);
+ GNUNET_MQ_send (ash->client->mq, env);
+ cleanup_as_handle (ash);
+}
+
+/**
+ * Send a reference error response
+ *
+ * @param ash our attribute store handle
+ * @param success the success status
+ */
+static void
+send_ref_error (struct AttributeStoreHandle *ash)
+{
+ struct GNUNET_MQ_Envelope *env;
+ struct SuccessResultMessage *acr_msg;
+
+ ash->ns_qe = NULL;
+ GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
+ ash->client->store_op_tail,
+ ash);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
+ env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
+ acr_msg->id = htonl (ash->r_id);
+ acr_msg->op_result = htonl (GNUNET_SYSERR);
+ GNUNET_MQ_send (ash->client->mq, env);
+ cleanup_as_handle (ash);
+}
+
+/**
+ * Error looking up potential attestation. Abort.
+ *
+ * @param cls our attribute store handle
+ */
+static void
+attest_error (void *cls)
+{
+ struct AttributeStoreHandle *ash = cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to check for existing Attestation\n");
+ cleanup_as_handle (ash);
+ GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+ return;
+}
+
+/**
+* Check for existing record before storing reference
+*
+* @param cls our attribute store handle
+* @param zone zone we are iterating
+* @param label label of the records
+* @param rd_count record count
+* @param rd records
+*/
+static void
+attest_add_cb (void *cls,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+ const char *label,
+ unsigned int rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+ struct AttributeStoreHandle *ash = cls;
+ char *buf;
+ size_t buf_size;
+ buf_size = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (ash->attest);
+ buf = GNUNET_malloc (buf_size);
+ GNUNET_RECLAIM_ATTESTATION_serialize (ash->attest, buf);
+ if (0 == rd_count )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Storing new Attestation\n");
+ struct GNUNET_GNSRECORD_Data rd_new[1];
+ rd_new[0].data_size = buf_size;
+ rd_new[0].data = buf;
+ rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR;
+ rd_new[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+ rd_new[0].expiration_time = ash->exp.rel_value_us;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
+ ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
+ &ash->identity,
+ label,
+ 1,
+ rd_new,
+ &attest_store_cont,
+ ash);
+ GNUNET_free (buf);
+ return;
+ }
+ if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[0].record_type)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Existing Attestation location is not an Attestation\n");
+ send_ref_error (ash);
+ return;
+ }
+ struct GNUNET_GNSRECORD_Data rd_new[rd_count];
+ for (int i = 0; i<rd_count; i++)
+ {
+ rd_new[i] = rd[i];
+ }
+ rd_new[0].data_size = buf_size;
+ rd_new[0].data = buf;
+ rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR;
+ rd_new[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+ rd_new[0].expiration_time = ash->exp.rel_value_us;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
+ ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
+ &ash->identity,
+ label,
+ rd_count,
+ rd_new,
+ &attest_store_cont,
+ ash);
+ GNUNET_free (buf);
+}
+
+/**
+ * Add a new attestation
+ *
+ * @param cls the AttributeStoreHandle
+ */
+static void
+attest_store_task (void *cls)
+{
+ struct AttributeStoreHandle *ash = cls;
+ char *label;
+
+ // Give the ash a new id if unset
+ if (0 == ash->attest->id)
+ ash->attest->id
+ = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
+ label = GNUNET_STRINGS_data_to_string_alloc (&ash->attest->id,
+ sizeof(uint64_t));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Looking up existing data under label %s\n", label);
+// Test for the content of the existing ID
+ ash->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
+ &ash->identity,
+ label,
+ &attest_error,
+ ash,
+ &attest_add_cb,
+ ash);
+ GNUNET_free (label);
+}
+
+/**
+ * Check an attestation store message
+ *
+ * @param cls unused
+ * @param sam the message to check
+ */
+static int
+check_attestation_store_message (void *cls,
+ const struct AttributeStoreMessage *sam)
+{
+ uint16_t size;
+
+ size = ntohs (sam->header.size);
+ if (size <= sizeof(struct AttributeStoreMessage))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+/**
+* Handle an attestation store message
+*
+* @param cls our client
+* @param sam the message to handle
+*/
+static void
+handle_attestation_store_message (void *cls,
+ const struct AttributeStoreMessage *sam)
+{
+ struct AttributeStoreHandle *ash;
+ struct IdpClient *idp = cls;
+ size_t data_len;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_STORE message\n");
+
+ data_len = ntohs (sam->attr_len);
+
+ ash = GNUNET_new (struct AttributeStoreHandle);
+ ash->attest = GNUNET_RECLAIM_ATTESTATION_deserialize ((char *) &sam[1],
+ data_len);
+
+ ash->r_id = ntohl (sam->id);
+ ash->identity = sam->identity;
+ ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
+ GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
+
+ GNUNET_SERVICE_client_continue (idp->client);
+ ash->client = idp;
+ GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
+ GNUNET_SCHEDULER_add_now (&attest_store_task, ash);
+}
+
+/**
+ * Error looking up potential reference value. Abort.
+ *
+ * @param cls our attribute store handle
+ */
+static void
+ref_error (void *cls)
+{
+ struct AttributeStoreHandle *ash = cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to find Attestation entry for Attestation reference\n");
+ cleanup_as_handle (ash);
+ GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+ return;
+}
+
+/**
+ * Error looking up potential reference value. Abort.
+ *
+ * @param cls our attribute delete handle
+ */
+static void
+ref_del_error (void *cls)
+{
+ struct AttributeDeleteHandle *adh = cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to find Attestation entry for Attestation reference\n");
+ cleanup_adh (adh);
+ GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+ return;
+}
+/**
+* Reference store result handler
+*
+* @param cls our attribute store handle
+* @param success GNUNET_OK if successful
+* @param emsg error message (NULL if success=GNUNET_OK)
+*/
+static void
+reference_store_cont (void *cls, int32_t success, const char *emsg)
+{
+ struct AttributeStoreHandle *ash = cls;
+ struct GNUNET_MQ_Envelope *env;
+ struct SuccessResultMessage *acr_msg;
+
+ ash->ns_qe = NULL;
+ GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
+ ash->client->store_op_tail,
+ ash);
+
+ if (GNUNET_SYSERR == success)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to store reference %s\n",
+ emsg);
+ cleanup_as_handle (ash);
+ GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
+ env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
+ acr_msg->id = htonl (ash->r_id);
+ acr_msg->op_result = htonl (GNUNET_OK);
+ GNUNET_MQ_send (ash->client->mq, env);
+ cleanup_as_handle (ash);
+}
+
+
+/**
+* Check for existing record before storing reference
+*
+* @param cls our attribute store handle
+* @param zone zone we are iterating
+* @param label label of the records
+* @param rd_count record count
+* @param rd records
+*/
+static void
+ref_add_cb (void *cls,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+ const char *label,
+ unsigned int rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+ struct AttributeStoreHandle *ash = cls;
+ char *buf;
+ size_t buf_size;
+ buf_size = GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (ash->reference);
+ buf = GNUNET_malloc (buf_size);
+ GNUNET_RECLAIM_ATTESTATION_REF_serialize (ash->reference, buf);
+ struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *ref;
+ char *data_tmp;
+ if (0 == rd_count )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to find Attestation entry for Attestation reference\n");
+ send_ref_error (ash);
+ return;
+ }
+ if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[0].record_type)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Intended Reference storage location is not an attestation\n");
+ send_ref_error (ash);
+ return;
+ }
+ struct GNUNET_GNSRECORD_Data rd_new[rd_count + 1];
+ int i;
+ for (i = 0; i<rd_count; i++)
+ {
+ data_tmp = GNUNET_malloc (rd[i].data_size);
+ GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
+ ref = GNUNET_RECLAIM_ATTESTATION_REF_deserialize (data_tmp, htons (
+ rd[i].data_size));
+ rd_new[i] = rd[i];
+ if ((strcmp (ash->reference->name,ref->name) == 0)&&
+ (strcmp (ash->reference->reference_value,ref->reference_value)==0) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Reference already stored\n");
+ reference_store_cont (ash,GNUNET_OK, NULL);
+ return;
+ }
+ }
+ rd_new[rd_count].data_size = buf_size;
+ rd_new[rd_count].data = buf;
+ rd_new[rd_count].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE;
+ rd_new[rd_count].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+ rd_new[rd_count].expiration_time = ash->exp.rel_value_us;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
+ ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
+ &ash->identity,
+ label,
+ rd_count + 1,
+ rd_new,
+ &reference_store_cont,
+ ash);
+ GNUNET_free (buf);
+}
+
+/**
+ * Add a new reference
+ *
+ * @param cls the AttributeStoreHandle
+ */
+static void
+reference_store_task (void *cls)
+{
+ struct AttributeStoreHandle *ash = cls;
+ char *label;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing reference\n");
+
+ // Give the ash a new id if unset
+ if (0 == ash->reference->id)
+ {
+ if (0 == ash->reference->id_attest)
+ {
+ ash->reference->id = GNUNET_CRYPTO_random_u64 (
+ GNUNET_CRYPTO_QUALITY_STRONG,
+ UINT64_MAX);
+ }
+ else
+ {
+ ash->reference->id = ash->reference->id_attest;
+ }
+ }
+
+ label = GNUNET_STRINGS_data_to_string_alloc (&ash->reference->id,
+ sizeof(uint64_t));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Looking up existing data under label %s\n", label);
+// Test for the content of the existing ID
+
+ ash->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
+ &ash->identity,
+ label,
+ &ref_error,
+ ash,
+ &ref_add_cb,
+ ash);
+ GNUNET_free (label);
+}
+
+/**
+ * Check an attestation reference store message
+ *
+ * @param cls unused
+ * @param sam the message to check
+ */
+static int
+check_reference_store_message (void *cls,
+ const struct
+ AttributeStoreMessage *sam)
+{
+ uint16_t size;
+
+ size = ntohs (sam->header.size);
+ if (size <= sizeof(struct AttributeStoreMessage))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Handle an attestation reference store message
+ *
+ * @param cls our client
+ * @param sam the message to handle
+ */
+static void
+handle_reference_store_message (void *cls,
+ const struct AttributeStoreMessage *sam)
+{
+ struct AttributeStoreHandle *ash;
+ struct IdpClient *idp = cls;
+ size_t data_len;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REFERENCE_STORE message\n");
+
+ data_len = ntohs (sam->attr_len);
+ ash = GNUNET_new (struct AttributeStoreHandle);
+ ash->reference = GNUNET_RECLAIM_ATTESTATION_REF_deserialize ((char *) &sam[1],
+ data_len);
+ ash->r_id = ntohl (sam->id);
+ ash->identity = sam->identity;
+ ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
+ GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
+
+
+ GNUNET_SERVICE_client_continue (idp->client);
+ ash->client = idp;
+ GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
+ GNUNET_SCHEDULER_add_now (&reference_store_task, ash);
+}
+/**
* Send a deletion success response
*
* @param adh our attribute deletion handle
@@ -1066,15 +1565,21 @@ ticket_iter (void *cls,
struct AttributeDeleteHandle *adh = cls;
struct TicketRecordsEntry *le;
int has_changed = GNUNET_NO;
-
for (int i = 0; i < rd_count; i++)
{
if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
continue;
- if (0 != memcmp (rd[i].data, &adh->claim->id, sizeof(uint64_t)))
- continue;
+ if (adh->claim != NULL)
+ if (0 != memcmp (rd[i].data, &adh->claim->id, sizeof(uint64_t)))
+ continue;
+ if (adh->attest != NULL)
+ if (0 != memcmp (rd[i].data, &adh->attest->id, sizeof(uint64_t)))
+ continue;
+ if (adh->reference != NULL)
+ if (0 != memcmp (rd[i].data, &adh->reference->id, sizeof(uint64_t)))
+ continue;
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Attribute to delete found (%s)\n",
+ "Attribute or Attestation/Reference to delete found (%s)\n",
adh->label);
has_changed = GNUNET_YES;
break;
@@ -1136,7 +1641,7 @@ update_tickets (void *cls)
if (NULL == adh->tickets_to_update_head)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Finished updatding tickets, success\n");
+ "Finished updating tickets, success\n");
send_delete_response (adh, GNUNET_OK);
cleanup_adh (adh);
return;
@@ -1164,9 +1669,18 @@ update_tickets (void *cls)
int j = 0;
for (int i = 0; i < le->rd_count; i++)
{
- if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
- && (0 == memcmp (rd[i].data, &adh->claim->id, sizeof(uint64_t))))
- continue;
+ if (adh->claim != NULL)
+ if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
+ && (0 == memcmp (rd[i].data, &adh->claim->id, sizeof(uint64_t))))
+ continue;
+ if (adh->attest != NULL)
+ if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
+ && (0 == memcmp (rd[i].data, &adh->attest->id, sizeof(uint64_t))))
+ continue;
+ if (adh->reference != NULL)
+ if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
+ && (0 == memcmp (rd[i].data, &adh->reference->id, sizeof(uint64_t))))
+ continue;
rd_new[j] = rd[i];
j++;
}
@@ -1192,7 +1706,6 @@ static void
ticket_iter_fin (void *cls)
{
struct AttributeDeleteHandle *adh = cls;
-
adh->ns_it = NULL;
GNUNET_SCHEDULER_add_now (&update_tickets, adh);
}
@@ -1309,6 +1822,8 @@ handle_attribute_delete_message (void *cls,
adh = GNUNET_new (struct AttributeDeleteHandle);
adh->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *) &dam[1],
data_len);
+ adh->reference = NULL;
+ adh->attest = NULL;
adh->r_id = ntohl (dam->id);
adh->identity = dam->identity;
@@ -1326,6 +1841,256 @@ handle_attribute_delete_message (void *cls,
adh);
}
+/**
+ * Attestation deleted callback
+ *
+ * @param cls our handle
+ * @param success success status
+ * @param emsg error message (NULL if success=GNUNET_OK)
+ */
+static void
+attest_delete_cont (void *cls, int32_t success, const char *emsg)
+{
+ struct AttributeDeleteHandle *adh = cls;
+
+ adh->ns_qe = NULL;
+ if (GNUNET_SYSERR == success)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error deleting attestation %s\n",
+ adh->label);
+ send_delete_response (adh, GNUNET_SYSERR);
+ cleanup_adh (adh);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
+ GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
+}
+
+/**
+ * Check attestation delete message format
+ *
+ * @cls unused
+ * @dam message to check
+ */
+static int
+check_attestation_delete_message (void *cls,
+ const struct AttributeDeleteMessage *dam)
+{
+ uint16_t size;
+
+ size = ntohs (dam->header.size);
+ if (size <= sizeof(struct AttributeDeleteMessage))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Handle attestation deletion
+ *
+ * @param cls our client
+ * @param dam deletion message
+ */
+static void
+handle_attestation_delete_message (void *cls,
+ const struct AttributeDeleteMessage *dam)
+{
+ struct AttributeDeleteHandle *adh;
+ struct IdpClient *idp = cls;
+ size_t data_len;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_DELETE message\n");
+
+ data_len = ntohs (dam->attr_len);
+
+ adh = GNUNET_new (struct AttributeDeleteHandle);
+ adh->attest = GNUNET_RECLAIM_ATTESTATION_deserialize ((char *) &dam[1],
+ data_len);
+ adh->reference = NULL;
+ adh->claim = NULL;
+
+ adh->r_id = ntohl (dam->id);
+ adh->identity = dam->identity;
+ adh->label
+ = GNUNET_STRINGS_data_to_string_alloc (&adh->attest->id, sizeof(uint64_t));
+ GNUNET_SERVICE_client_continue (idp->client);
+ adh->client = idp;
+ GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
+ adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
+ &adh->identity,
+ adh->label,
+ 0,
+ NULL,
+ &attest_delete_cont,
+ adh);
+}
+
+
+
+/**
+* Reference deleted callback
+*
+* @param cls our handle
+* @param success success status
+* @param emsg error message (NULL if success=GNUNET_OK)
+*/
+static void
+reference_delete_cont (void *cls, int32_t success, const char *emsg)
+{
+ struct AttributeDeleteHandle *adh = cls;
+
+ adh->ns_qe = NULL;
+ if (GNUNET_SYSERR == success)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error deleting reference %s\n",
+ adh->label);
+ send_delete_response (adh, GNUNET_SYSERR);
+ cleanup_adh (adh);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
+ //GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
+ send_delete_response (adh, GNUNET_OK);
+ cleanup_adh (adh);
+ return;
+}
+
+static void
+ref_del_cb (void *cls,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+ const char *label,
+ unsigned int rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+
+ struct AttributeDeleteHandle *adh = cls;
+ char *data_tmp;
+ struct GNUNET_GNSRECORD_Data rd_new[rd_count - 1];
+ struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *ref;
+ size_t attr_len;
+
+ if (0 == rd_count )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to find Attestation entry for Attestation reference\n");
+ cleanup_adh (adh);
+ GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+ return;
+ }
+ if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[0].record_type)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Intended Reference location is not an attestation\n");
+ cleanup_adh (adh);
+ GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+ return;
+ }
+ rd_new[0] = rd[0];
+ int i;
+ int j = 1;
+ for (i = 1; i<rd_count; i++)
+ {
+ data_tmp = GNUNET_malloc (rd[i].data_size);
+ GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
+ attr_len = htons (rd[i].data_size);
+ ref = GNUNET_RECLAIM_ATTESTATION_REF_deserialize (data_tmp, attr_len);
+ if (NULL == ref )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to parse attestation reference from %s\n",
+ data_tmp);
+ rd_new[j] = rd[i];
+ j += 1;
+ continue;
+ }
+ if ((strcmp (adh->reference->name,ref->name) == 0)&&
+ (strcmp (adh->reference->reference_value,ref->reference_value)==0) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Found reference to delete.\n");
+ }
+ else
+ {
+ rd_new[j] = rd[i];
+ j += 1;
+ }
+ GNUNET_free (data_tmp);
+ }
+ adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
+ &adh->identity,
+ label,
+ j,
+ rd_new,
+ &reference_delete_cont,
+ adh);
+}
+
+/**
+ * Check an attestation reference delete message
+ *
+ * @param cls unused
+ * @param sam the message to check
+ */
+static int
+check_reference_delete_message (void *cls,
+ const struct AttributeDeleteMessage *dam)
+{
+ uint16_t size;
+
+ size = ntohs (dam->header.size);
+ if (size <= sizeof(struct AttributeDeleteMessage))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+/**
+ * Handle reference deletion
+ *
+ * @param cls our client
+ * @param dam deletion message
+ */
+static void
+handle_reference_delete_message (void *cls,
+ const struct AttributeDeleteMessage *dam)
+{
+ struct AttributeDeleteHandle *adh;
+ struct IdpClient *idp = cls;
+ size_t data_len;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REFERENCE_DELETE message\n");
+ data_len = ntohs (dam->attr_len);
+ adh = GNUNET_new (struct AttributeDeleteHandle);
+ adh->reference = GNUNET_RECLAIM_ATTESTATION_REF_deserialize ((char *) &dam[1],
+ data_len);
+ adh->attest = NULL;
+ adh->claim = NULL;
+
+ adh->r_id = ntohl (dam->id);
+ adh->identity = dam->identity;
+ adh->label
+ = GNUNET_STRINGS_data_to_string_alloc (&adh->reference->id,
+ sizeof(uint64_t));
+ GNUNET_SERVICE_client_continue (idp->client);
+ adh->client = idp;
+ GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
+ adh->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
+ &adh->identity,
+ adh->label,
+ &ref_del_error,
+ adh,
+ &ref_del_cb,
+ adh);
+}
+
+
/*************************************************
* Attrubute iteration
@@ -1372,7 +2137,7 @@ attr_iter_error (void *cls)
/**
- * Got record. Return if it is an attribute.
+ * Got record. Return if it is an attribute or attestation/reference.
*
* @param cls our attribute iterator
* @param zone zone we are iterating
@@ -1388,35 +2153,103 @@ attr_iter_cb (void *cls,
const struct GNUNET_GNSRECORD_Data *rd)
{
struct AttributeIterator *ai = cls;
- struct AttributeResultMessage *arm;
struct GNUNET_MQ_Envelope *env;
char *data_tmp;
- if (rd_count != 1)
+ if (rd_count == 0)
{
GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
return;
}
+ if (rd_count > 1)
+ {
+ if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[0].record_type)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Found Ticket. Ignoring.\n");
+ GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
+ return;
+ }
+ else if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[0].record_type)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Non-Attestation record with multiple entries found: %u\n",
+ rd[0].record_type);
+ GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
+ return;
+ }
+ }
- if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd->record_type)
+ for (int i = 0; i<rd_count; i++)
{
- GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
- return;
+ if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd[i].record_type) &&
+ (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[i].record_type) &&
+ (GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE != rd[i].record_type))
+ {
+ GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
+ return;
+ }
+
+ if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR == rd[i].record_type )
+ {
+ struct AttributeResultMessage *arm;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n",
+ label);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending ATTRIBUTE_RESULT message\n");
+ env = GNUNET_MQ_msg_extra (arm,
+ rd[i].data_size,
+ GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
+ arm->id = htonl (ai->request_id);
+ arm->attr_len = htons (rd[i].data_size);
+ GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
+ data_tmp = (char *) &arm[1];
+ GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
+ GNUNET_MQ_send (ai->client->mq, env);
+ }
+ else
+ {
+ if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR == rd[i].record_type )
+ {
+ struct AttributeResultMessage *arm;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attestation under: %s\n",
+ label);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending ATTESTATION_RESULT message\n");
+ env = GNUNET_MQ_msg_extra (arm,
+ rd[i].data_size,
+ GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT);
+ arm->id = htonl (ai->request_id);
+ arm->attr_len = htons (rd[i].data_size);
+ GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
+ data_tmp = (char *) &arm[1];
+ GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
+ GNUNET_MQ_send (ai->client->mq, env);
+ }
+ else
+ {
+ struct ReferenceResultMessage *rrm;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found reference under: %s\n",
+ label);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending REFERENCE_RESULT message\n");
+ env = GNUNET_MQ_msg_extra (rrm,
+ rd[i].data_size + rd[0].data_size,
+ GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_RESULT);
+ rrm->id = htonl (ai->request_id);
+ rrm->attest_len = htons (rd[0].data_size);
+ rrm->ref_len = htons (rd[i].data_size);
+ GNUNET_CRYPTO_ecdsa_key_get_public (zone, &rrm->identity);
+ data_tmp = (char *) &rrm[1];
+ GNUNET_memcpy (data_tmp, rd[0].data, rd[0].data_size);
+ data_tmp += rd[0].data_size;
+ GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
+ GNUNET_MQ_send (ai->client->mq, env);
+ }
+ }
}
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n", label);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
- env = GNUNET_MQ_msg_extra (arm,
- rd->data_size,
- GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
- arm->id = htonl (ai->request_id);
- arm->attr_len = htons (rd->data_size);
- GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
- data_tmp = (char *) &arm[1];
- GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
- GNUNET_MQ_send (ai->client->mq, env);
}
-
/**
* Iterate over zone to get attributes
*
@@ -1742,10 +2575,26 @@ GNUNET_SERVICE_MAIN (
GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
struct AttributeStoreMessage,
NULL),
+ GNUNET_MQ_hd_var_size (attestation_store_message,
+ GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE,
+ struct AttributeStoreMessage,
+ NULL),
GNUNET_MQ_hd_var_size (attribute_delete_message,
GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
struct AttributeDeleteMessage,
NULL),
+ GNUNET_MQ_hd_var_size (attestation_delete_message,
+ GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE,
+ struct AttributeDeleteMessage,
+ NULL),
+ GNUNET_MQ_hd_var_size (reference_store_message,
+ GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_STORE,
+ struct AttributeStoreMessage,
+ NULL),
+ GNUNET_MQ_hd_var_size (reference_delete_message,
+ GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_DELETE,
+ struct AttributeDeleteMessage,
+ NULL),
GNUNET_MQ_hd_fixed_size (
iteration_start,
GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
diff --git a/src/reclaim/gnunet-service-reclaim_tickets.c b/src/reclaim/gnunet-service-reclaim_tickets.c
index 4d1a26333..b022225b8 100644
--- a/src/reclaim/gnunet-service-reclaim_tickets.c
+++ b/src/reclaim/gnunet-service-reclaim_tickets.c
@@ -667,8 +667,7 @@ rvk_move_attr_cb (void *cls,
const struct GNUNET_GNSRECORD_Data *rd)
{
struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
- struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
- struct GNUNET_GNSRECORD_Data new_rd;
+ struct GNUNET_GNSRECORD_Data new_rd[rd_count];
struct RevokedAttributeEntry *le;
char *new_label;
char *attr_data;
@@ -677,7 +676,7 @@ rvk_move_attr_cb (void *cls,
if (0 == rd_count)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "The attribute %s no longer exists!\n",
+ "The claim %s no longer exists!\n",
label);
le = rvk->move_attr;
rvk->move_attr = le->next;
@@ -686,32 +685,82 @@ rvk_move_attr_cb (void *cls,
GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk);
return;
}
- /** find a new place for this attribute **/
- rvk->move_attr->new_id =
- GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
- new_rd = *rd;
- claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize (rd->data, rd->data_size);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Attribute to update: Name=%s, ID=%" PRIu64 "\n",
- claim->name,
- claim->id);
- claim->id = rvk->move_attr->new_id;
- new_rd.data_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (claim);
- attr_data = GNUNET_malloc (rd->data_size);
- new_rd.data_size = GNUNET_RECLAIM_ATTRIBUTE_serialize (claim, attr_data);
- new_rd.data = attr_data;
- new_label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id,
- sizeof(uint64_t));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label);
+ rvk->move_attr->new_id =GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
+ new_label=NULL;
+ attr_data=NULL;
+ //new_rd = *rd;
+ for (int i = 0; i < rd_count; i++)
+ {
+ if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR == rd[i].record_type)
+ {
+ /** find a new place for this attribute **/
+ struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
+ claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize (rd[i].data, rd[i].data_size);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Attribute to update: Name=%s, ID=%" PRIu64 "\n",
+ claim->name,
+ claim->id);
+ claim->id = rvk->move_attr->new_id;
+ new_rd[i].data_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (claim);
+ attr_data = GNUNET_malloc (rd[i].data_size);
+ new_rd[i].data_size = GNUNET_RECLAIM_ATTRIBUTE_serialize (claim, attr_data);
+ new_rd[i].data = attr_data;
+ new_rd[i].record_type = rd[i].record_type;
+ new_rd[i].flags = rd[i].flags;
+ new_rd[i].expiration_time = rd[i].expiration_time;
+ new_label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id,
+ sizeof(uint64_t));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label);
+ GNUNET_free (claim);
+ } else if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR == rd[i].record_type)
+ {
+ struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
+ attest=GNUNET_RECLAIM_ATTESTATION_deserialize(rd[i].data, rd[i].data_size);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Attestation to update: Name=%s, ID=%" PRIu64 "\n",
+ attest->name,
+ attest->id);
+ attest->id = rvk->move_attr->new_id;
+ new_rd[i].data_size = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (attest);
+ attr_data = GNUNET_malloc (rd[i].data_size);
+ new_rd[i].data_size = GNUNET_RECLAIM_ATTESTATION_serialize (attest, attr_data);
+ new_rd[i].data = attr_data;
+ new_rd[i].record_type = rd[i].record_type;
+ new_rd[i].flags = rd[i].flags;
+ new_rd[i].expiration_time = rd[i].expiration_time;
+ new_label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id, sizeof(uint64_t));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attestation %s\n", new_label);
+ GNUNET_free (attest);
+ } else if (GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE == rd[i].record_type)
+ {
+ struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference;
+ reference=GNUNET_RECLAIM_ATTESTATION_REF_deserialize(rd[i].data, rd[i].data_size);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Reference to update: Name=%s, ID=%" PRIu64 "\n",
+ reference->name,
+ reference->id);
+ reference->id = rvk->move_attr->new_id;
+ reference->id_attest = rvk->move_attr->new_id;
+ new_rd[i].data_size = GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (reference);
+ attr_data = GNUNET_malloc (rd[i].data_size);
+ new_rd[i].data_size = GNUNET_RECLAIM_ATTESTATION_REF_serialize (reference, attr_data);
+ new_rd[i].data = attr_data;
+ new_label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id, sizeof(uint64_t));
+ new_rd[i].record_type = rd[i].record_type;
+ new_rd[i].flags = rd[i].flags;
+ new_rd[i].expiration_time = rd[i].expiration_time;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding reference %s\n", new_label);
+ GNUNET_free (reference);
+ }
+ }
rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
- &rvk->identity,
- new_label,
- 1,
- &new_rd,
- &move_attr_finished,
- rvk);
+ &rvk->identity,
+ new_label,
+ rd_count,
+ new_rd,
+ &move_attr_finished,
+ rvk);
GNUNET_free (new_label);
- GNUNET_free (claim);
GNUNET_free (attr_data);
}
@@ -745,7 +794,7 @@ move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rvk)
}
label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id,
sizeof(uint64_t));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Moving attribute %s\n", label);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Moving claim %s\n", label);
rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
&rvk->identity,
@@ -982,21 +1031,70 @@ process_parallel_lookup_result (void *cls,
GNUNET_free (parallel_lookup);
- if (1 != rd_count)
- GNUNET_break (0); // FIXME: We should never find this.
- if (rd->record_type == GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR)
+ if (0 == rd_count)
+ GNUNET_break (0);
+ // REMARK: It is possible now to find rd_count > 1
+ for (int i = 0; i < rd_count; i++)
{
- attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
- attr_le->claim =
- GNUNET_RECLAIM_ATTRIBUTE_deserialize (rd->data, rd->data_size);
- GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
- cth->attrs->list_tail,
- attr_le);
- }
+ if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR == rd[i].record_type)
+ {
+ attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+ attr_le->claim =
+ GNUNET_RECLAIM_ATTRIBUTE_deserialize (rd[i].data, rd[i].data_size);
+ GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
+ cth->attrs->list_tail,
+ attr_le);
+ attr_le->reference = NULL;
+ attr_le->attest = NULL;
+ }
+ else if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR == rd[i].record_type)
+ {
+ /**Ignore all plain attestations
+ *attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+ *attr_le->attest =
+ * GNUNET_RECLAIM_ATTESTATION_deserialize (rd[i].data, rd[i].data_size);
+ *GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
+ * cth->attrs->list_tail,
+ * attr_le);
+ */
+ continue;
+ }
+ else if (GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE == rd[i].record_type)
+ {
+ struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *attr_le2;
+ attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+ attr_le2 = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+ if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR == rd[0].record_type)
+ {
+ attr_le->attest = GNUNET_RECLAIM_ATTESTATION_deserialize (rd[0].data,
+ rd[0].
+ data_size);
+ attr_le2->reference =
+ GNUNET_RECLAIM_ATTESTATION_REF_deserialize (rd[i].data,
+ rd[i].data_size);
+ attr_le->claim = NULL;
+ attr_le->reference = NULL;
+ attr_le2->claim = NULL;
+ attr_le2->attest = NULL;
+ GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
+ cth->attrs->list_tail,
+ attr_le);
+ GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
+ cth->attrs->list_tail,
+ attr_le2);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Parallel Lookup of Reference without Attestation");
+ continue;
+ }
+
+ }
+ }
if (NULL != cth->parallel_lookups_head)
return; // Wait for more
-
/* Else we are done */
cth->cb (cth->cb_cls, &cth->ticket.identity, cth->attrs, GNUNET_OK, NULL);
cleanup_cth (cth);
@@ -1076,7 +1174,7 @@ lookup_authz_cb (void *cls,
GNUNET_GNS_lookup (gns,
lbl,
&cth->ticket.identity,
- GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR,
+ GNUNET_GNSRECORD_TYPE_ANY,
GNUNET_GNS_LO_DEFAULT,
&process_parallel_lookup_result,
parallel_lookup);
@@ -1223,6 +1321,7 @@ issue_ticket (struct TicketIssueHandle *ih)
char *label;
size_t list_len = 1;
int i;
+ char *attest_string;
for (le = ih->attrs->list_head; NULL != le; le = le->next)
list_len++;
@@ -1232,8 +1331,51 @@ issue_ticket (struct TicketIssueHandle *ih)
i = 0;
for (le = ih->attrs->list_head; NULL != le; le = le->next)
{
- attrs_record[i].data = &le->claim->id;
- attrs_record[i].data_size = sizeof(le->claim->id);
+ if (NULL != le->claim)
+ {
+ attrs_record[i].data = &le->claim->id;
+ attrs_record[i].data_size = sizeof(le->claim->id);
+ }
+ else if (NULL != le->attest)
+ {
+ // REMARK: Since we only store IDs, the references are irrelevant
+ int j = 0;
+ GNUNET_asprintf (&attest_string,"%d",le->attest->id);
+ while (j<i)
+ {
+ if (0 == strcmp (attest_string,GNUNET_STRINGS_data_to_string_alloc (
+ attrs_record[j].data, attrs_record[j].data_size)))
+ break;
+ j++;
+ }
+ if (j < i)
+ {
+ list_len--;
+ continue;
+ }
+ attrs_record[i].data = &le->attest->id;
+ attrs_record[i].data_size = sizeof(le->attest->id);
+ }
+ else if (NULL != le->reference)
+ {
+ list_len--;
+ continue;
+ /*
+ int j = 0;
+ GNUNET_asprintf (&attest_string,"%d",le->attest->id);
+ while (j<i)
+ {
+ if (strcmp(attest_string, GNUNET_STRINGS_data_to_string_alloc (
+ attrs_record[j].data, attrs_record[j].data_size)))
+ break;
+ j++;
+ }
+ if (j < i)
+ continue;
+ attrs_record[i].data = &le->reference->id;
+ attrs_record[i].data_size = sizeof(le->reference->id);
+ */
+ }
/**
* FIXME: Should this be the attribute expiration time or ticket
* refresh interval? Probably min(attrs.expiration)
@@ -1344,14 +1486,34 @@ filter_tickets_cb (void *cls,
for (le = tih->attrs->list_head; NULL != le; le = le->next)
{
// cmp attr_ref id with requested attr id
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- " %" PRIu64 "\n %" PRIu64 "\n",
- *((uint64_t *) rd[i].data),
- le->claim->id);
-
+ if (NULL !=le->claim)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ " %" PRIu64 "\n %" PRIu64 "\n",
+ *((uint64_t *) rd[i].data),
+ le->claim->id);
+ if (0 == memcmp (rd[i].data, &le->claim->id, sizeof(uint64_t)))
+ found_attrs_cnt++;
+ }
+ else if (NULL !=le->attest)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ " %" PRIu64 "\n %" PRIu64 "\n",
+ *((uint64_t *) rd[i].data),
+ le->attest->id);
+ if (0 == memcmp (rd[i].data, &le->attest->id, sizeof(uint64_t)))
+ found_attrs_cnt++;
+ }
+ else if (NULL != le->reference)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ " %" PRIu64 "\n %" PRIu64 "\n",
+ *((uint64_t *) rd[i].data),
+ le->reference->id);
+ if (0 == memcmp (rd[i].data, &le->reference->id, sizeof(uint64_t)))
+ found_attrs_cnt++;
+ }
- if (0 == memcmp (rd[i].data, &le->claim->id, sizeof(uint64_t)))
- found_attrs_cnt++;
}
}
diff --git a/src/reclaim/json_reclaim.c b/src/reclaim/json_reclaim.c
index e029fdfb6..a464a9088 100644
--- a/src/reclaim/json_reclaim.c
+++ b/src/reclaim/json_reclaim.c
@@ -48,6 +48,7 @@ parse_attr (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
const char *val_str = NULL;
const char *type_str = NULL;
const char *id_str = NULL;
+ const char *flag_str = NULL;
char *data;
int unpack_state;
uint32_t type;
@@ -63,7 +64,7 @@ parse_attr (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
}
// interpret single attribute
unpack_state = json_unpack (root,
- "{s:s, s?s, s:s, s:s!}",
+ "{s:s, s?s, s:s, s:s, s?s!}",
"name",
&name_str,
"id",
@@ -71,7 +72,9 @@ parse_attr (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
"type",
&type_str,
"value",
- &val_str);
+ &val_str,
+ "flag",
+ &flag_str);
if ((0 != unpack_state) || (NULL == name_str) || (NULL == val_str) ||
(NULL == type_str))
{
@@ -264,3 +267,217 @@ GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket)
*ticket = NULL;
return ret;
}
+
+/**
+ * Parse given JSON object to an attestation claim
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_attest (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
+{
+ struct GNUNET_RECLAIM_ATTESTATION_Claim *attr;
+ const char *name_str = NULL;
+ const char *val_str = NULL;
+ const char *type_str = NULL;
+ const char *id_str = NULL;
+ char *data;
+ int unpack_state;
+ uint32_t type;
+ size_t data_size;
+
+ GNUNET_assert (NULL != root);
+
+ if (! json_is_object (root))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error json is not array nor object!\n");
+ return GNUNET_SYSERR;
+ }
+ // interpret single attribute
+ unpack_state = json_unpack (root,
+ "{s:s, s?s, s:s, s:s!}",
+ "name",
+ &name_str,
+ "id",
+ &id_str,
+ "type",
+ &type_str,
+ "value",
+ &val_str);
+ if ((0 != unpack_state) || (NULL == name_str) || (NULL == val_str) ||
+ (NULL == type_str))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error json object has a wrong format!\n");
+ return GNUNET_SYSERR;
+ }
+ type = GNUNET_RECLAIM_ATTESTATION_typename_to_number (type_str);
+ if (GNUNET_SYSERR ==
+ (GNUNET_RECLAIM_ATTESTATION_string_to_value (type,
+ val_str,
+ (void **) &data,
+ &data_size)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Attestation value invalid!\n");
+ return GNUNET_SYSERR;
+ }
+ attr = GNUNET_RECLAIM_ATTESTATION_claim_new (name_str, type, data, data_size);
+ if ((NULL == id_str) || (0 == strlen (id_str)))
+ attr->id = 0;
+ else
+ GNUNET_STRINGS_string_to_data (id_str,
+ strlen (id_str),
+ &attr->id,
+ sizeof(uint64_t));
+
+ *(struct GNUNET_RECLAIM_ATTESTATION_Claim **) spec->ptr = attr;
+ return GNUNET_OK;
+}
+
+/**
+ * Cleanup data left from parsing RSA public key.
+ *
+ * @param cls closure, NULL
+ * @param[out] spec where to free the data
+ */
+static void
+clean_attest (void *cls, struct GNUNET_JSON_Specification *spec)
+{
+ struct GNUNET_RECLAIM_ATTESTATION_Claim **attr;
+
+ attr = (struct GNUNET_RECLAIM_ATTESTATION_Claim **) spec->ptr;
+ if (NULL != *attr)
+ {
+ GNUNET_free (*attr);
+ *attr = NULL;
+ }
+}
+/**
+ * JSON Specification for Reclaim attestation claims.
+ *
+ * @param ticket struct of GNUNET_RECLAIM_ATTESTATION_Claim to fill
+ * @return JSON Specification
+ */
+struct GNUNET_JSON_Specification
+GNUNET_RECLAIM_JSON_spec_claim_attest (struct
+ GNUNET_RECLAIM_ATTESTATION_Claim **attr)
+{
+ struct GNUNET_JSON_Specification ret = { .parser = &parse_attest,
+ .cleaner = &clean_attest,
+ .cls = NULL,
+ .field = NULL,
+ .ptr = attr,
+ .ptr_size = 0,
+ .size_ptr = NULL };
+
+ *attr = NULL;
+ return ret;
+}
+
+/**
+ * Parse given JSON object to an attestation claim
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_attest_ref (void *cls, json_t *root, struct
+ GNUNET_JSON_Specification *spec)
+{
+ struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
+ const char *name_str = NULL;
+ const char *ref_val_str = NULL;
+ const char *ref_id_str = NULL;
+ const char *id_str = NULL;
+ int unpack_state;
+
+ GNUNET_assert (NULL != root);
+
+ if (! json_is_object (root))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error json is not array nor object!\n");
+ return GNUNET_SYSERR;
+ }
+ // interpret single reference
+ unpack_state = json_unpack (root,
+ "{s:s, s?s, s:s, s:s!}",
+ "name",
+ &name_str,
+ "id",
+ &id_str,
+ "ref_id",
+ &ref_id_str,
+ "ref_value",
+ &ref_val_str);
+ if ((0 != unpack_state) || (NULL == name_str) || (NULL == ref_val_str) ||
+ (NULL == ref_id_str))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error json object has a wrong format!\n");
+ return GNUNET_SYSERR;
+ }
+
+ attr = GNUNET_RECLAIM_ATTESTATION_reference_new (name_str, ref_val_str);
+
+ attr->id = 0;
+
+ if ((NULL == ref_id_str) || (0 == strlen (ref_id_str)))
+ attr->id_attest = 0;
+ else
+ GNUNET_STRINGS_string_to_data (ref_id_str,
+ strlen (ref_id_str),
+ &attr->id_attest,
+ sizeof(uint64_t));
+
+ *(struct GNUNET_RECLAIM_ATTESTATION_REFERENCE **) spec->ptr = attr;
+ return GNUNET_OK;
+}
+
+/**
+ * Cleanup data left from parsing RSA public key.
+ *
+ * @param cls closure, NULL
+ * @param[out] spec where to free the data
+ */
+static void
+clean_attest_ref (void *cls, struct GNUNET_JSON_Specification *spec)
+{
+ struct GNUNET_RECLAIM_ATTESTATION_REFERENCE **attr;
+
+ attr = (struct GNUNET_RECLAIM_ATTESTATION_REFERENCE **) spec->ptr;
+ if (NULL != *attr)
+ {
+ GNUNET_free (*attr);
+ *attr = NULL;
+ }
+}
+
+/**
+ * JSON Specification for Reclaim attestation references.
+ *
+ * @param ticket struct of GNUNET_RECLAIM_ATTESTATION_REFERENCE to fill
+ * @return JSON Specification
+ */
+struct GNUNET_JSON_Specification
+GNUNET_RECLAIM_JSON_spec_claim_attest_ref (struct
+ GNUNET_RECLAIM_ATTESTATION_REFERENCE
+ **attr)
+{
+ struct GNUNET_JSON_Specification ret = { .parser = &parse_attest_ref,
+ .cleaner = &clean_attest_ref,
+ .cls = NULL,
+ .field = NULL,
+ .ptr = attr,
+ .ptr_size = 0,
+ .size_ptr = NULL };
+
+ *attr = NULL;
+ return ret;
+} \ No newline at end of file
diff --git a/src/reclaim/json_reclaim.h b/src/reclaim/json_reclaim.h
index 3fd26167f..9e6479e5e 100644
--- a/src/reclaim/json_reclaim.h
+++ b/src/reclaim/json_reclaim.h
@@ -46,3 +46,22 @@ GNUNET_RECLAIM_JSON_spec_claim (struct GNUNET_RECLAIM_ATTRIBUTE_Claim **attr);
*/
struct GNUNET_JSON_Specification
GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket);
+
+/**
+ * JSON Specification for Reclaim attestation claims.
+ *
+ * @param ticket struct of GNUNET_RECLAIM_ATTESTATION_Claim to fill
+ * @return JSON Specification
+ */
+struct GNUNET_JSON_Specification
+GNUNET_RECLAIM_JSON_spec_claim_attest (struct
+ GNUNET_RECLAIM_ATTESTATION_Claim **attr);
+
+ /**
+ * JSON Specification for Reclaim attestation references.
+ *
+ * @param ticket struct of GNUNET_RECLAIM_ATTESTATION_REFERENCE to fill
+ * @return JSON Specification
+ */
+ struct GNUNET_JSON_Specification
+ GNUNET_RECLAIM_JSON_spec_claim_attest_ref(struct GNUNET_RECLAIM_ATTESTATION_REFERENCE **attr);
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
index 1c3d65f35..2ce462854 100644
--- a/src/reclaim/oidc_helper.c
+++ b/src/reclaim/oidc_helper.c
@@ -118,7 +118,7 @@ fix_base64 (char *str)
char *
OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
- const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+ struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
const struct GNUNET_TIME_Relative *expiration_time,
const char *nonce,
const char *secret_key)
@@ -131,13 +131,22 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
char *subject;
char *header;
char *body_str;
+ char *aggr_names_str;
+ char *aggr_sources_str;
+ char *aggr_sources_jwt_str;
+ char *source_name;
char *result;
char *header_base64;
char *body_base64;
char *signature_target;
char *signature_base64;
char *attr_val_str;
+ char *attest_val_str;
json_t *body;
+ json_t *aggr_names;
+ json_t *aggr_sources;
+ json_t *aggr_sources_jwt;
+ uint64_t attest_arr[GNUNET_RECLAIM_ATTRIBUTE_list_count_attest (attrs)];
// iat REQUIRED time now
time_now = GNUNET_TIME_absolute_get ();
@@ -156,6 +165,8 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
GNUNET_CRYPTO_EcdsaPublicKey));
header = create_jwt_header ();
body = json_object ();
+ aggr_names = json_object ();
+ aggr_sources = json_object ();
// iss REQUIRED case sensitive server uri with https
// The issuer is the local reclaim instance (e.g.
@@ -180,18 +191,111 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
// nonce
if (NULL != nonce)
json_object_set_new (body, "nonce", json_string (nonce));
-
+ int i = 0;
+ attest_val_str = NULL;
+ aggr_names_str = NULL;
+ aggr_sources_str = NULL;
+ aggr_sources_jwt_str = NULL;
+ source_name = NULL;
for (le = attrs->list_head; NULL != le; le = le->next)
{
- attr_val_str =
- GNUNET_RECLAIM_ATTRIBUTE_value_to_string (le->claim->type,
- le->claim->data,
- le->claim->data_size);
- json_object_set_new (body, le->claim->name, json_string (attr_val_str));
- GNUNET_free (attr_val_str);
+
+ if (le->claim != NULL)
+ {
+
+ attr_val_str =
+ GNUNET_RECLAIM_ATTRIBUTE_value_to_string (le->claim->type,
+ le->claim->data,
+ le->claim->data_size);
+ json_object_set_new (body, le->claim->name, json_string (attr_val_str));
+ GNUNET_free (attr_val_str);
+ }
+ else if (NULL != le->reference)
+ {
+ // Check if attest is there
+ int j = 0;
+ while (j<i)
+ {
+ if (attest_arr[j] == le->reference->id_attest)
+ break;
+ j++;
+ }
+ if (j==i)
+ {
+ // Attest not yet existent. Append to the end of the list
+ GNUNET_CONTAINER_DLL_remove (attrs->list_head, attrs->list_tail, le);
+ GNUNET_CONTAINER_DLL_insert_tail (attrs->list_head, attrs->list_tail,
+ le);
+ continue;
+ }
+ else
+ {
+ // Attestation is existing, hence take the respective source str
+ GNUNET_asprintf (&source_name,
+ "src%d",
+ j);
+ json_object_set_new (aggr_names, le->reference->name, json_string (
+ source_name));
+ }
+
+ }
+ else if (NULL != le->attest)
+ {
+ // We assume that at max 99 different attestations
+ int j = 0;
+ while (j<i)
+ {
+ if (attest_arr[j] == le->attest->id)
+ break;
+ j++;
+ }
+ if (j==i)
+ {
+ // New Attestation
+ attest_arr[i] = le->attest->id;
+ GNUNET_asprintf (&source_name,
+ "src%d",
+ i);
+ aggr_sources_jwt = json_object ();
+ attest_val_str = GNUNET_RECLAIM_ATTESTATION_value_to_string (
+ le->attest->type, le->attest->data, le->attest->data_size);
+ json_object_set_new (aggr_sources_jwt, "JWT",json_string (
+ attest_val_str) );
+ aggr_sources_jwt_str = json_dumps (aggr_sources_jwt, JSON_INDENT (0)
+ | JSON_COMPACT);
+ json_object_set_new (aggr_sources, source_name,json_string (
+ aggr_sources_jwt_str));
+ i++;
+ }
+ else
+ {
+ // Attestation already existent. Ignore
+ continue;
+ }
+
+ }
+ }
+ if (NULL != attest_val_str)
+ GNUNET_free (attest_val_str);
+ if (NULL != source_name)
+ GNUNET_free (source_name);
+ if (0!=i)
+ {
+ aggr_names_str = json_dumps (aggr_names, JSON_INDENT (0) | JSON_COMPACT);
+ aggr_sources_str = json_dumps (aggr_sources, JSON_INDENT (0)
+ | JSON_COMPACT);
+ json_object_set_new (body, "_claim_names", json_string (aggr_names_str));
+ json_object_set_new (body, "_claim_sources", json_string (
+ aggr_sources_str));
}
+
+ json_decref (aggr_names);
+ json_decref (aggr_sources);
+ json_decref (aggr_sources_jwt);
+
body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
json_decref (body);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str);
GNUNET_STRINGS_base64_encode (header, strlen (header), &header_base64);
fix_base64 (header_base64);
@@ -226,6 +330,12 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
GNUNET_free (signature_target);
GNUNET_free (header);
GNUNET_free (body_str);
+ if (NULL != aggr_sources_str)
+ GNUNET_free (aggr_sources_str);
+ if (NULL != aggr_names_str)
+ GNUNET_free (aggr_names_str);
+ if (NULL != aggr_sources_jwt_str)
+ GNUNET_free (aggr_sources_jwt_str);
GNUNET_free (signature_base64);
GNUNET_free (body_base64);
GNUNET_free (header_base64);
diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h
index 1774618e8..a7072755b 100644
--- a/src/reclaim/oidc_helper.h
+++ b/src/reclaim/oidc_helper.h
@@ -51,7 +51,7 @@
char*
OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
- const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+ struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
const struct GNUNET_TIME_Relative *expiration_time,
const char *nonce,
const char *secret_key);
diff --git a/src/reclaim/plugin_gnsrecord_reclaim.c b/src/reclaim/plugin_gnsrecord_reclaim.c
index d530ef01d..f7145a272 100644
--- a/src/reclaim/plugin_gnsrecord_reclaim.c
+++ b/src/reclaim/plugin_gnsrecord_reclaim.c
@@ -54,6 +54,8 @@ value_to_string (void *cls, uint32_t type, const void *data, size_t data_size)
case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF:
case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER:
+ case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR:
+ case GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE:
return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
default:
@@ -93,6 +95,8 @@ string_to_value (void *cls, uint32_t type, const char *s, void **data,
case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF:
case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER:
case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
+ case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR:
+ case GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE:
return GNUNET_STRINGS_string_to_data (s, strlen (s), *data, *data_size);
default:
@@ -112,10 +116,12 @@ static struct
} name_map[] = {
{ "RECLAIM_ATTR", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR },
{ "RECLAIM_ATTR_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF },
+ { "RECLAIM_ATTEST", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR },
{ "RECLAIM_MASTER", GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER },
{ "RECLAIM_OIDC_CLIENT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT },
{ "RECLAIM_OIDC_REDIRECT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT },
{ "RECLAIM_TICKET", GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET },
+ { "RECLAIM_REFERENCE", GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE },
{ NULL, UINT32_MAX }
};
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c
index 92a1de621..741094f21 100644
--- a/src/reclaim/plugin_rest_openid_connect.c
+++ b/src/reclaim/plugin_rest_openid_connect.c
@@ -120,6 +120,11 @@
#define OIDC_NONCE_KEY "nonce"
/**
+ * OIDC claims key
+ */
+#define OIDC_CLAIMS_KEY "claims"
+
+/**
* OIDC PKCE code challenge
*/
#define OIDC_CODE_CHALLENGE_KEY "code_challenge"
@@ -291,6 +296,11 @@ struct OIDC_Variables
char *nonce;
/**
+ * The OIDC claims
+ */
+ char *claims;
+
+ /**
* The OIDC response type
*/
char *response_type;
@@ -560,7 +570,12 @@ cleanup_handle (struct RequestHandle *handle)
{
claim_tmp = claim_entry;
claim_entry = claim_entry->next;
- GNUNET_free (claim_tmp->claim);
+ if (NULL != claim_tmp->claim)
+ GNUNET_free (claim_tmp->claim);
+ if (NULL != claim_tmp->attest)
+ GNUNET_free (claim_tmp->attest);
+ if (NULL != claim_tmp->reference)
+ GNUNET_free (claim_tmp->reference);
GNUNET_free (claim_tmp);
}
GNUNET_free (handle->attr_list);
@@ -697,7 +712,7 @@ return_userinfo_response (void *cls)
struct MHD_Response *resp;
result_str = json_dumps (handle->oidc->response, 0);
-
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,"ID-Token: %s\n",result_str);
resp = GNUNET_REST_create_response (result_str);
handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
GNUNET_free (result_str);
@@ -838,7 +853,7 @@ login_redirect (void *cls)
&login_base_url))
{
GNUNET_asprintf (&new_redirect,
- "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s",
+ "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s",
login_base_url,
OIDC_RESPONSE_TYPE_KEY,
handle->oidc->response_type,
@@ -854,7 +869,10 @@ login_redirect (void *cls)
(NULL != handle->oidc->code_challenge) ?
handle->oidc->code_challenge : "",
OIDC_NONCE_KEY,
- (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "");
+ (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "",
+ OIDC_CLAIMS_KEY,
+ (NULL != handle->oidc->claims) ? handle->oidc->claims :
+ "");
resp = GNUNET_REST_create_response ("");
MHD_add_response_header (resp, "Location", new_redirect);
GNUNET_free (login_base_url);
@@ -973,12 +991,14 @@ oidc_collect_finished_cb (void *cls)
/**
- * Collects all attributes for an ego if in scope parameter
+ * Collects all attributes/references for an ego if in scope parameter
*/
static void
oidc_attr_collect (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
- const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+ const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
{
struct RequestHandle *handle = cls;
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
@@ -986,39 +1006,92 @@ oidc_attr_collect (void *cls,
char *scope_variable;
char delimiter[] = " ";
- if ((NULL == attr->name) || (NULL == attr->data))
+ if ((NULL == attr) && (NULL == reference))
{
GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
return;
}
-
- scope_variables = GNUNET_strdup (handle->oidc->scope);
- scope_variable = strtok (scope_variables, delimiter);
- while (NULL != scope_variable)
- {
- if (0 == strcmp (attr->name, scope_variable))
- break;
- scope_variable = strtok (NULL, delimiter);
- }
- if (NULL == scope_variable)
+ if (NULL != reference)
{
- GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+ if ((NULL == reference->name) || (NULL == reference->reference_value))
+ {
+ return;
+ }
+ scope_variables = GNUNET_strdup (handle->oidc->scope);
+ scope_variable = strtok (scope_variables, delimiter);
+ while (NULL != scope_variable)
+ {
+ if (0 == strcmp (reference->name, scope_variable))
+ break;
+ scope_variable = strtok (NULL, delimiter);
+ }
+ if (NULL == scope_variable)
+ {
+ GNUNET_free (scope_variables);
+ return;
+ }
GNUNET_free (scope_variables);
- return;
+ struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le2;
+ le2 = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+ le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+ le->claim = NULL;
+ le->reference = NULL;
+ le->attest = GNUNET_RECLAIM_ATTESTATION_claim_new (attest->name,
+ attest->type,
+ attest->data,
+ attest->data_size);
+ le->attest->id = attest->id;
+ le2->attest = NULL;
+ le2->claim = NULL;
+ le2->reference = GNUNET_RECLAIM_ATTESTATION_reference_new (reference->name,
+ reference->
+ reference_value);
+ le2->reference->id = reference->id;
+ le2->reference->id_attest = reference->id_attest;
+ GNUNET_CONTAINER_DLL_insert (handle->attr_list->list_head,
+ handle->attr_list->list_tail,
+ le);
+ GNUNET_CONTAINER_DLL_insert (handle->attr_list->list_head,
+ handle->attr_list->list_tail,
+ le2);
+ }
+ else if (NULL != attr)
+ {
+ if ((NULL == attr->name) || (NULL == attr->data))
+ {
+ GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+ return;
+ }
+ scope_variables = GNUNET_strdup (handle->oidc->scope);
+ scope_variable = strtok (scope_variables, delimiter);
+ while (NULL != scope_variable)
+ {
+ if (0 == strcmp (attr->name, scope_variable))
+ break;
+ scope_variable = strtok (NULL, delimiter);
+ }
+ if (NULL == scope_variable)
+ {
+ GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+ GNUNET_free (scope_variables);
+ return;
+ }
+ GNUNET_free (scope_variables);
+ le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+ le->reference = NULL;
+ le->attest = NULL;
+ le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name,
+ attr->type,
+ attr->data,
+ attr->data_size);
+ le->claim->id = attr->id;
+ le->claim->flag = attr->flag;
+
+ GNUNET_CONTAINER_DLL_insert (handle->attr_list->list_head,
+ handle->attr_list->list_tail,
+ le);
+ GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
}
- GNUNET_free (scope_variables);
-
- le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
- le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name,
- attr->type,
- attr->data,
- attr->data_size);
- le->claim->id = attr->id;
- le->claim->version = attr->version;
- GNUNET_CONTAINER_DLL_insert (handle->attr_list->list_head,
- handle->attr_list->list_tail,
- le);
- GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
}
@@ -1304,6 +1377,9 @@ build_authz_response (void *cls)
// OPTIONAL value: nonce
handle->oidc->nonce = get_url_parameter_copy (handle, OIDC_NONCE_KEY);
+ // OPTIONAL value: claims
+ handle->oidc->claims = get_url_parameter_copy (handle, OIDC_CLAIMS_KEY);
+
// TODO check other values if needed
number_of_ignored_parameter =
sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
@@ -1454,6 +1530,9 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
handle->ego_entry = handle->ego_tail;
}
}
+ handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scope: %s\n",GNUNET_strdup (
+ handle->oidc->scope));
if (NULL == handle->tld)
GNUNET_CONFIGURATION_iterate_section_values (cfg, "gns", tld_iter, handle);
if (NULL == handle->tld)
@@ -1857,28 +1936,97 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
/**
- * Collects claims and stores them in handle
- */
+ * Collects claims and stores them in handle
+ */
static void
consume_ticket (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
- const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+ const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
{
struct RequestHandle *handle = cls;
- char *tmp_value;
- json_t *value;
-
if (NULL == identity)
{
GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle);
return;
}
- tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
- attr->data,
- attr->data_size);
- value = json_string (tmp_value);
- json_object_set_new (handle->oidc->response, attr->name, value);
- GNUNET_free (tmp_value);
+ if (NULL != attr)
+ {
+ char *tmp_value;
+ json_t *value;
+ tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
+ attr->data,
+ attr->data_size);
+ value = json_string (tmp_value);
+ json_object_set_new (handle->oidc->response, attr->name, value);
+ GNUNET_free (tmp_value);
+ }
+ else if ((NULL != attest) && (NULL != reference))
+ {
+ json_t *claim_sources;
+ json_t *claim_sources_jwt;
+ json_t *claim_names;
+ char *attest_val_str;
+ claim_sources=json_object_get(handle->oidc->response,"_claim_sources");
+ claim_names=json_object_get(handle->oidc->response,"_claim_names");
+ attest_val_str = GNUNET_RECLAIM_ATTESTATION_value_to_string (attest->type,
+ attest->data,
+ attest->
+ data_size);
+ if ((NULL == claim_sources) && (NULL == claim_names) )
+ {
+ claim_sources = json_object ();
+ claim_names = json_object ();
+ }
+ char *source_name;
+ int i = 0;
+ GNUNET_asprintf (&source_name,"src%d",i);
+ while (NULL != (claim_sources_jwt = json_object_get (claim_sources,
+ source_name)))
+ {
+ if (0 == strcmp (json_string_value (json_object_get (claim_sources_jwt,
+ "JWT")),
+ attest_val_str))
+ {
+ // Adapt only the claim names
+ json_object_set_new (claim_names, reference->name, json_string (
+ source_name));
+ json_object_set (handle->oidc->response, "_claim_names",claim_names);
+ handle->oidc->response = json_deep_copy(handle->oidc->response);
+ break;
+ }
+ i++;
+ GNUNET_asprintf (&source_name,"src%d",i);
+ }
+
+ // Create new one
+ if (NULL == claim_sources_jwt)
+ {
+ claim_sources_jwt = json_object ();
+ // Set the JWT for names
+ json_object_set_new (claim_names, reference->name, json_string (
+ source_name));
+ // Set the JWT for the inner source
+ json_object_set_new (claim_sources_jwt, "JWT", json_string (
+ attest_val_str));
+ // Set the JWT for the source
+ json_object_set_new (claim_sources, source_name,claim_sources_jwt);
+ // Set as claims
+ json_object_set (handle->oidc->response, "_claim_names", claim_names);
+ json_object_set (handle->oidc->response, "_claim_sources",claim_sources);
+ handle->oidc->response = json_deep_copy(handle->oidc->response);
+ }
+
+ json_decref (claim_sources);
+ json_decref (claim_names);
+ json_decref (claim_sources_jwt);
+ GNUNET_free (attest_val_str);
+ }
+ else
+ {
+ // REMARK: We should not find any claim, one of attest/ref is NULL
+ }
}
diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c
index 9a75b2d16..dcda75b65 100644
--- a/src/reclaim/plugin_rest_reclaim.c
+++ b/src/reclaim/plugin_rest_reclaim.c
@@ -37,7 +37,6 @@
#include "gnunet_rest_plugin.h"
#include "gnunet_signatures.h"
#include "json_reclaim.h"
-
/**
* REST root namespace
*/
@@ -49,6 +48,11 @@
#define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/reclaim/attributes"
/**
+ * Attestation namespace
+ */
+#define GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE "/reclaim/attestation"
+
+/**
* Ticket namespace
*/
#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/reclaim/tickets"
@@ -272,6 +276,8 @@ cleanup_handle (struct RequestHandle *handle)
claim_tmp = claim_entry;
claim_entry = claim_entry->next;
GNUNET_free (claim_tmp->claim);
+ GNUNET_free (claim_tmp->attest);
+ GNUNET_free (claim_tmp->reference);
GNUNET_free (claim_tmp);
}
GNUNET_free (handle->attr_list);
@@ -360,6 +366,21 @@ finished_cont (void *cls, int32_t success, const char *emsg)
GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
}
+static void
+delete_finished_cb (void *cls, int32_t success, const char *emsg)
+{
+ struct RequestHandle *handle = cls;
+ struct MHD_Response *resp;
+
+ resp = GNUNET_REST_create_response (emsg);
+ if (GNUNET_OK != success)
+ {
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+ GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+}
/**
* Return attributes for identity
@@ -434,6 +455,661 @@ ticket_collect (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
}
+static void
+add_attestation_ref_cont (struct GNUNET_REST_RequestHandle *con_handle,
+ const char *url,
+ void *cls)
+{
+ struct RequestHandle *handle = cls;
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+ const char *identity;
+ struct EgoEntry *ego_entry;
+ struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attribute;
+ struct GNUNET_TIME_Relative exp;
+ char term_data[handle->rest_handle->data_size + 1];
+ json_t *data_json;
+ json_error_t err;
+ struct GNUNET_JSON_Specification attrspec[] =
+ { GNUNET_RECLAIM_JSON_spec_claim_attest_ref (&attribute),
+ GNUNET_JSON_spec_end () };
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Adding an attestation reference for %s.\n",
+ handle->url);
+ if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen (
+ "reference/") + 1 >= strlen (
+ handle->url))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ identity = handle->url + strlen (
+ GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen ("reference/")
+ + 1;
+ for (ego_entry = handle->ego_head; NULL != ego_entry;
+ ego_entry = ego_entry->next)
+ if (0 == strcmp (identity, ego_entry->identifier))
+ break;
+ if (NULL == ego_entry)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
+ return;
+ }
+ identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+ if (0 >= handle->rest_handle->data_size)
+ {
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+
+ term_data[handle->rest_handle->data_size] = '\0';
+ GNUNET_memcpy (term_data,
+ handle->rest_handle->data,
+ handle->rest_handle->data_size);
+ data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
+ json_decref (data_json);
+ if (NULL == attribute)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to parse attestation reference from %s\n",
+ term_data);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ /**
+ * New ID for attribute
+ */
+ if (0 == attribute->id)
+ attribute->id = attribute->id_attest;
+ handle->idp = GNUNET_RECLAIM_connect (cfg);
+ exp = GNUNET_TIME_UNIT_HOURS;
+ handle->idp_op = GNUNET_RECLAIM_attestation_reference_store (handle->idp,
+ identity_priv,
+ attribute,
+ &exp,
+ &finished_cont,
+ handle);
+ GNUNET_JSON_parse_free (attrspec);
+}
+
+static void
+parse_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
+ const char *url,
+ void *cls)
+{
+ struct RequestHandle *handle = cls;
+
+ char term_data[handle->rest_handle->data_size + 1];
+ json_t *data_json;
+ json_error_t err;
+ int unpack_state;
+ struct MHD_Response *resp;
+ char *val_str = NULL;
+ const char *type_str = NULL;
+ term_data[handle->rest_handle->data_size] = '\0';
+ GNUNET_memcpy (term_data,
+ handle->rest_handle->data,
+ handle->rest_handle->data_size);
+ data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
+ GNUNET_assert (NULL != data_json);
+ if (! json_is_object (data_json))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error json is not array nor object!\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ unpack_state = json_unpack (data_json,
+ "{s:s, s:s!}",
+ "value",
+ &val_str,
+ "type",
+ &type_str);
+ if ((0 != unpack_state) || (NULL == val_str) || (NULL == type_str))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error json object has a wrong format!\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ if (0 == strcmp (type_str, "JWT"))
+ {
+ // The value is a JWT
+ char *decoded_jwt;
+ char delim[] = ".";
+ char *jwt_body = strtok (val_str, delim);
+ jwt_body = strtok (NULL, delim);
+ GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
+ (void **) &decoded_jwt);
+ resp = GNUNET_REST_create_response (decoded_jwt);
+ handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+ GNUNET_free (decoded_jwt);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error requested parsing type not supported!\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ cleanup_handle (handle);
+ json_decref (data_json);
+}
+
+static void
+add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
+ const char *url,
+ void *cls)
+{
+ struct RequestHandle *handle = cls;
+ /* Check for substring "reference" */
+ if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
+ handle->url))
+ {
+ if ( strncmp ("reference/", (handle->url + strlen (
+ GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
+ + 1), strlen (
+ "reference/")) == 0)
+ {
+ add_attestation_ref_cont (con_handle,url,cls);
+ return;
+ }
+ }
+ /* Check for substring "parse" */
+ if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
+ handle->url))
+ {
+ if ( strncmp ("parse", (handle->url + strlen (
+ GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
+ + 1), strlen (
+ "parse")) == 0)
+ {
+ parse_attestation_cont (con_handle,url,cls);
+ return;
+ }
+ }
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+ const char *identity;
+ struct EgoEntry *ego_entry;
+ struct GNUNET_RECLAIM_ATTESTATION_Claim *attribute;
+ struct GNUNET_TIME_Relative exp;
+ char term_data[handle->rest_handle->data_size + 1];
+ json_t *data_json;
+ json_error_t err;
+ struct GNUNET_JSON_Specification attrspec[] =
+ { GNUNET_RECLAIM_JSON_spec_claim_attest (&attribute),
+ GNUNET_JSON_spec_end () };
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Adding an attestation for %s.\n",
+ handle->url);
+ if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) >= strlen (
+ handle->url))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ identity = handle->url + strlen (
+ GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + 1;
+
+ for (ego_entry = handle->ego_head; NULL != ego_entry;
+ ego_entry = ego_entry->next)
+ if (0 == strcmp (identity, ego_entry->identifier))
+ break;
+
+ if (NULL == ego_entry)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
+ return;
+ }
+ identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+
+ if (0 >= handle->rest_handle->data_size)
+ {
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+
+ term_data[handle->rest_handle->data_size] = '\0';
+ GNUNET_memcpy (term_data,
+ handle->rest_handle->data,
+ handle->rest_handle->data_size);
+ data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
+ json_decref (data_json);
+ if (NULL == attribute)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to parse attestation from %s\n",
+ term_data);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ /**
+ * New ID for attribute
+ */
+ if (0 == attribute->id)
+ attribute->id =
+ GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
+ handle->idp = GNUNET_RECLAIM_connect (cfg);
+ exp = GNUNET_TIME_UNIT_HOURS;
+ handle->idp_op = GNUNET_RECLAIM_attestation_store (handle->idp,
+ identity_priv,
+ attribute,
+ &exp,
+ &finished_cont,
+ handle);
+ GNUNET_JSON_parse_free (attrspec);
+}
+
+/**
+ * Collect all references for an ego
+ *
+ */
+static void
+ref_collect (void *cls,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+ const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
+{
+ struct RequestHandle *handle = cls;
+ json_t *attr_obj;
+ char *id_str;
+ char *id_attest_str;
+
+ if (NULL == reference)
+ {
+ GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+ return;
+ }
+
+ if ((NULL == reference->name) || (NULL == reference->reference_value))
+ {
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding reference: %s\n",
+ reference->name);
+ attr_obj = json_object ();
+ json_object_set_new (attr_obj, "name", json_string (reference->name));
+ json_object_set_new (attr_obj, "ref_value", json_string (
+ reference->reference_value));
+ id_str = GNUNET_STRINGS_data_to_string_alloc (&reference->id,
+ sizeof(uint64_t));
+ id_attest_str = GNUNET_STRINGS_data_to_string_alloc (&reference->id_attest,
+ sizeof(uint64_t));
+ json_object_set_new (attr_obj, "id", json_string (id_str));
+ json_object_set_new (attr_obj, "ref_id", json_string (id_attest_str));
+ json_array_append (handle->resp_object, attr_obj);
+ json_decref (attr_obj);
+}
+
+/**
+ * Lists references for identity request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+list_reference_cont (struct GNUNET_REST_RequestHandle *con_handle,
+ const char *url,
+ void *cls)
+{
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+ struct RequestHandle *handle = cls;
+ struct EgoEntry *ego_entry;
+ char *identity;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Getting references for %s.\n",
+ handle->url);
+ if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen (
+ "reference/") + 1 >= strlen (
+ handle->url))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ identity = handle->url + strlen (
+ GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen ("reference/")
+ + 1;
+ for (ego_entry = handle->ego_head; NULL != ego_entry;
+ ego_entry = ego_entry->next)
+ if (0 == strcmp (identity, ego_entry->identifier))
+ break;
+ handle->resp_object = json_array ();
+
+ if (NULL == ego_entry)
+ {
+ // Done
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
+ GNUNET_SCHEDULER_add_now (&return_response, handle);
+ return;
+ }
+ priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+ handle->idp = GNUNET_RECLAIM_connect (cfg);
+ handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp,
+ priv_key,
+ &collect_error_cb,
+ handle,
+ &ref_collect,
+ handle,
+ &collect_finished_cb,
+ handle);
+}
+
+/**
+ * Collect all attestations for an ego
+ *
+ */
+static void
+attest_collect (void *cls,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+ const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
+{
+ struct RequestHandle *handle = cls;
+ json_t *attr_obj;
+ const char *type;
+ char *tmp_value;
+ char *id_str;
+
+
+ if (NULL != reference)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Attestation Collection with Reference\n");
+ return;
+ }
+ if (NULL == attest)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Attestation Collection with empty Attestation\n");
+ GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+ return;
+ }
+
+ if ((NULL == attest->name) || (NULL == attest->data))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Attestation Collection with empty Name/Value\n");
+ GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attestation: %s\n",
+ attest->name);
+
+ tmp_value = GNUNET_RECLAIM_ATTESTATION_value_to_string (attest->type,
+ attest->data,
+ attest->data_size);
+ attr_obj = json_object ();
+ json_object_set_new (attr_obj, "value", json_string (tmp_value));
+ json_object_set_new (attr_obj, "name", json_string (attest->name));
+ type = GNUNET_RECLAIM_ATTESTATION_number_to_typename (attest->type);
+ json_object_set_new (attr_obj, "type", json_string (type));
+ id_str = GNUNET_STRINGS_data_to_string_alloc (&attest->id, sizeof(uint64_t));
+ json_object_set_new (attr_obj, "id", json_string (id_str));
+ json_array_append (handle->resp_object, attr_obj);
+ json_decref (attr_obj);
+ GNUNET_free (tmp_value);
+ GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+}
+
+
+/**
+ * Lists attestation for identity request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
+ const char *url,
+ void *cls)
+{
+ struct RequestHandle *handle = cls;
+ /* Check for substring "reference" */
+ if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
+ handle->url))
+ {
+ if ( strncmp ("reference/", (handle->url + strlen (
+ GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
+ + 1), strlen (
+ "reference/")) == 0)
+ {
+ list_reference_cont (con_handle,url,cls);
+ return;
+ }
+ }
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+ struct EgoEntry *ego_entry;
+ char *identity;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Getting attestations for %s.\n",
+ handle->url);
+ if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) >= strlen (
+ handle->url))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ identity = handle->url + strlen (
+ GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + 1;
+
+ for (ego_entry = handle->ego_head; NULL != ego_entry;
+ ego_entry = ego_entry->next)
+ if (0 == strcmp (identity, ego_entry->identifier))
+ break;
+ handle->resp_object = json_array ();
+
+
+ if (NULL == ego_entry)
+ {
+ // Done
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
+ GNUNET_SCHEDULER_add_now (&return_response, handle);
+ return;
+ }
+ priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+ handle->idp = GNUNET_RECLAIM_connect (cfg);
+ handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp,
+ priv_key,
+ &collect_error_cb,
+ handle,
+ &attest_collect,
+ handle,
+ &collect_finished_cb,
+ handle);
+}
+
+/**
+ * Deletes reference from an identity
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+delete_attestation_ref_cont (struct GNUNET_REST_RequestHandle *con_handle,
+ const char *url,
+ void *cls)
+{
+ struct RequestHandle *handle = cls;
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+ struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
+ struct EgoEntry *ego_entry;
+ char *identity;
+ char *identity_id_str;
+ char *id;
+ char term_data[handle->rest_handle->data_size + 1];
+ json_t *data_json;
+ json_error_t err;
+
+ struct GNUNET_JSON_Specification attrspec[] =
+ { GNUNET_RECLAIM_JSON_spec_claim_attest_ref (&attr),
+ GNUNET_JSON_spec_end () };
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Deleting attestation reference.\n");
+ if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen (
+ "reference/") + 1 >= strlen (
+ handle->url))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ identity_id_str = strdup (handle->url + strlen (
+ GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
+ + strlen ("reference/")
+ + 1);
+ identity = strtok (identity_id_str, "/");
+ id = strtok (NULL, "/");
+
+ if ((NULL == identity) || (NULL == id))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ for (ego_entry = handle->ego_head; NULL != ego_entry;
+ ego_entry = ego_entry->next)
+ if (0 == strcmp (identity, ego_entry->identifier))
+ break;
+ handle->resp_object = json_array ();
+ if (NULL == ego_entry)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
+ GNUNET_SCHEDULER_add_now (&return_response, handle);
+ return;
+ }
+ priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+ if (0 >= handle->rest_handle->data_size)
+ {
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+
+ term_data[handle->rest_handle->data_size] = '\0';
+ GNUNET_memcpy (term_data,
+ handle->rest_handle->data,
+ handle->rest_handle->data_size);
+ data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
+ json_decref (data_json);
+ if (NULL == attr)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to parse attestation reference from %s\n",
+ term_data);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ GNUNET_STRINGS_string_to_data (id, strlen (id), &attr->id, sizeof(uint64_t));
+
+ handle->idp = GNUNET_RECLAIM_connect (cfg);
+ handle->idp_op = GNUNET_RECLAIM_attestation_reference_delete (handle->idp,
+ priv_key,
+ attr,
+ &
+ delete_finished_cb,
+ handle);
+ GNUNET_JSON_parse_free (attrspec);
+}
+
+
+/**
+ * Deletes attestation from an identity
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
+ const char *url,
+ void *cls)
+{
+ struct RequestHandle *handle = cls;
+ /* Check for substring "reference" */
+ if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
+ handle->url))
+ {
+ if ( strncmp ("reference", (handle->url + strlen (
+ GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
+ + 1), strlen (
+ "reference")) == 0)
+ {
+ delete_attestation_ref_cont (con_handle,url,cls);
+ return;
+ }
+ }
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+ struct GNUNET_RECLAIM_ATTESTATION_Claim attr;
+ struct EgoEntry *ego_entry;
+ char *identity_id_str;
+ char *identity;
+ char *id;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting attestation.\n");
+ if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) >= strlen (
+ handle->url))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ identity_id_str =
+ strdup (handle->url + strlen (
+ GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + 1);
+ identity = strtok (identity_id_str, "/");
+ id = strtok (NULL, "/");
+ if ((NULL == identity) || (NULL == id))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
+ GNUNET_free (identity_id_str);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+
+ for (ego_entry = handle->ego_head; NULL != ego_entry;
+ ego_entry = ego_entry->next)
+ if (0 == strcmp (identity, ego_entry->identifier))
+ break;
+ handle->resp_object = json_array ();
+ if (NULL == ego_entry)
+ {
+ // Done
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
+ GNUNET_free (identity_id_str);
+ GNUNET_SCHEDULER_add_now (&return_response, handle);
+ return;
+ }
+ priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+ handle->idp = GNUNET_RECLAIM_connect (cfg);
+ memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim));
+ GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(uint64_t));
+ attr.name = "";
+ handle->idp_op = GNUNET_RECLAIM_attestation_delete (handle->idp,
+ priv_key,
+ &attr,
+ &delete_finished_cb,
+ handle);
+ GNUNET_free (identity_id_str);
+}
+
/**
* List tickets for identity request
*
@@ -568,6 +1244,72 @@ add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
GNUNET_JSON_parse_free (attrspec);
}
+/**
+ * Parse a JWT and return the respective claim value as Attribute
+ *
+ * @param attest the jwt attestation
+ * @param claim the name of the claim in the JWT
+ *
+ * @return a GNUNET_RECLAIM_ATTRIBUTE_Claim, containing the new value
+ */
+struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
+parse_jwt (const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
+ const char *claim)
+{
+ char *jwt_string;
+ struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
+ char delim[] = ".";
+ const char *type_str = NULL;
+ const char *val_str = NULL;
+ char *data;
+ size_t data_size;
+ uint32_t type;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
+ char *decoded_jwt;
+ json_t *json_val;
+ json_error_t *json_err = NULL;
+
+ jwt_string = GNUNET_RECLAIM_ATTESTATION_value_to_string (attest->type,
+ attest->data,
+ attest->data_size);
+ char *jwt_body = strtok (jwt_string, delim);
+ jwt_body = strtok (NULL, delim);
+ GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
+ (void **) &decoded_jwt);
+ json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
+ const char *key;
+ json_t *value;
+ json_object_foreach (json_val, key, value) {
+ if (0 == strcasecmp (key,claim))
+ {
+ val_str = json_dumps (value, JSON_ENCODE_ANY);
+ }
+ }
+ type_str = "String";
+ type = GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (type_str);
+ if (GNUNET_SYSERR ==(GNUNET_RECLAIM_ATTRIBUTE_string_to_value (type,val_str,
+ (void **) &data,
+ &data_size)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Attribute value from JWT Parser invalid!\n");
+ GNUNET_RECLAIM_ATTRIBUTE_string_to_value (type,
+ "Error: Referenced Claim Name not Found",
+ (void **) &data,
+ &data_size);
+ attr = GNUNET_RECLAIM_ATTRIBUTE_claim_new (claim, type, data, data_size);
+ attr->id = attest->id;
+ attr->flag = 1;
+ }
+ else
+ {
+ attr = GNUNET_RECLAIM_ATTRIBUTE_claim_new (claim, type, data, data_size);
+ attr->id = attest->id;
+ attr->flag = 1;
+ }
+ return attr;
+}
+
/**
* Collect all attributes for an ego
@@ -576,40 +1318,93 @@ add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
static void
attr_collect (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
- const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+ const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
{
struct RequestHandle *handle = cls;
json_t *attr_obj;
const char *type;
- char *tmp_value;
char *id_str;
- if ((NULL == attr->name) || (NULL == attr->data))
+ if ((NULL == attr) && (NULL == reference))
{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Attribute Collection with empty Attribute/Reference\n");
GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
return;
}
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name);
-
- tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
- attr->data,
- attr->data_size);
+ if (NULL == attr)
+ {
- attr_obj = json_object ();
- json_object_set_new (attr_obj, "value", json_string (tmp_value));
- json_object_set_new (attr_obj, "name", json_string (attr->name));
- type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr->type);
- json_object_set_new (attr_obj, "type", json_string (type));
- id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(uint64_t));
- json_object_set_new (attr_obj, "id", json_string (id_str));
- json_array_append (handle->resp_object, attr_obj);
- json_decref (attr_obj);
- GNUNET_free (tmp_value);
- GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+ if ((NULL == reference->name) || (NULL == reference->reference_value))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Attribute Collection with empty Reference Name/Value\n");
+ return;
+ }
+ struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr2;
+ attr2 = parse_jwt (attest, reference->reference_value);
+ if (NULL == attr2)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Attribute Collection with unparsed Attestation\n");
+ return;
+ }
+ attr2->name = reference->name;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding reference as attribute: %s\n",
+ reference->name);
+ char *tmp_value;
+ tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr2->type,
+ attr2->data,
+ attr2->data_size);
+ attr_obj = json_object ();
+
+ json_object_set_new (attr_obj, "value", json_string (tmp_value));
+ json_object_set_new (attr_obj, "name", json_string (attr2->name));
+ json_object_set_new (attr_obj, "flag", json_string ("1"));
+ type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr2->type);
+ json_object_set_new (attr_obj, "type", json_string (type));
+ id_str = GNUNET_STRINGS_data_to_string_alloc (&attr2->id, sizeof(uint64_t));
+ json_object_set_new (attr_obj, "id", json_string (id_str));
+ json_array_append (handle->resp_object, attr_obj);
+ json_decref (attr_obj);
+ GNUNET_free (tmp_value);
+ }
+ else
+ {
+ if ((NULL == attr->name) || (NULL == attr->data))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Attribute Collection with empty Attribute Name/Value\n");
+ GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+ return;
+ }
+ char *tmp_value;
+ char *flag_str;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name);
+
+ tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
+ attr->data,
+ attr->data_size);
+
+ attr_obj = json_object ();
+ json_object_set_new (attr_obj, "value", json_string (tmp_value));
+ json_object_set_new (attr_obj, "name", json_string (attr->name));
+ GNUNET_asprintf (&flag_str,"%d",attr->flag);
+ json_object_set_new (attr_obj, "flag", json_string (flag_str));
+ type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr->type);
+ json_object_set_new (attr_obj, "type", json_string (type));
+ id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(uint64_t));
+ json_object_set_new (attr_obj, "id", json_string (id_str));
+ json_array_append (handle->resp_object, attr_obj);
+ json_decref (attr_obj);
+ GNUNET_free (tmp_value);
+ GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+ }
}
-
/**
* List attributes for identity request
*
@@ -665,23 +1460,6 @@ list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
}
-static void
-delete_finished_cb (void *cls, int32_t success, const char *emsg)
-{
- struct RequestHandle *handle = cls;
- struct MHD_Response *resp;
-
- resp = GNUNET_REST_create_response (emsg);
- if (GNUNET_OK != success)
- {
- GNUNET_SCHEDULER_add_now (&do_error, handle);
- return;
- }
- handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
- GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-}
-
-
/**
* List attributes for identity request
*
@@ -825,7 +1603,9 @@ revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
static void
consume_cont (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
- const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+ const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
{
struct RequestHandle *handle = cls;
char *val_str;
@@ -969,6 +1749,15 @@ init_cont (struct RequestHandle *handle)
GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES,
&delete_attribute_cont },
{ MHD_HTTP_METHOD_GET,
+ GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE,
+ &list_attestation_cont },
+ { MHD_HTTP_METHOD_POST,
+ GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE,
+ &add_attestation_cont },
+ { MHD_HTTP_METHOD_DELETE,
+ GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE,
+ &delete_attestation_cont },
+ { MHD_HTTP_METHOD_GET,
GNUNET_REST_API_NS_IDENTITY_TICKETS,
&list_tickets_cont },
{ MHD_HTTP_METHOD_POST,
diff --git a/src/reclaim/reclaim.h b/src/reclaim/reclaim.h
index 8e731812e..ff953a096 100644
--- a/src/reclaim/reclaim.h
+++ b/src/reclaim/reclaim.h
@@ -153,6 +153,45 @@ struct AttributeResultMessage
*/
};
+/**
+ * Reference plus Attestation is returned from the idp.
+ */
+struct ReferenceResultMessage
+{
+ /**
+ * Message header
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /**
+ * Length of serialized attestation data
+ */
+ uint16_t attest_len GNUNET_PACKED;
+
+ /**
+ * Length of serialized reference data
+ */
+ uint16_t ref_len GNUNET_PACKED;
+
+ /**
+ * always zero (for alignment)
+ */
+ uint16_t reserved GNUNET_PACKED;
+
+ /**
+ * The public key of the identity.
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey identity;
+
+ /* followed by:
+ * serialized reference data + attestation data
+ */
+};
/**
* Start a attribute iteration for the given identity
diff --git a/src/reclaim/reclaim_api.c b/src/reclaim/reclaim_api.c
index 7d4d7588a..847abb58a 100644
--- a/src/reclaim/reclaim_api.c
+++ b/src/reclaim/reclaim_api.c
@@ -486,7 +486,7 @@ handle_consume_ticket_result (void *cls,
uint32_t r_id = ntohl (msg->id);
attrs_len = ntohs (msg->attrs_len);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing attribute result.\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing ticket result.\n");
for (op = h->op_head; NULL != op; op = op->next)
@@ -498,22 +498,36 @@ handle_consume_ticket_result (void *cls,
{
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+ struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le2;
attrs =
GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char *) &msg[1], attrs_len);
if (NULL != op->ar_cb)
{
if (NULL == attrs)
{
- op->ar_cb (op->cls, &msg->identity, NULL);
+ op->ar_cb (op->cls, &msg->identity, NULL, NULL, NULL);
}
else
{
for (le = attrs->list_head; NULL != le; le = le->next)
- op->ar_cb (op->cls, &msg->identity, le->claim);
+ {
+ if (le->reference != NULL && le->attest == NULL)
+ {
+ for (le2 = attrs->list_head; NULL != le2; le2 = le2->next)
+ {
+ if (le2->attest != NULL && le2->attest->id == le->reference->id_attest)
+ {
+ op->ar_cb (op->cls, &msg->identity, le->claim, le2->attest, le->reference);
+ break;
+ }
+
+ }
+ }
+ }
GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
attrs = NULL;
}
- op->ar_cb (op->cls, NULL, NULL);
+ op->ar_cb (op->cls, NULL, NULL, NULL, NULL);
}
GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
free_op (op);
@@ -597,7 +611,7 @@ handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
if (NULL != op)
{
if (NULL != op->ar_cb)
- op->ar_cb (op->cls, NULL, NULL);
+ op->ar_cb (op->cls, NULL, NULL, NULL, NULL);
GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
free_op (op);
}
@@ -610,12 +624,111 @@ handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
if (NULL != it)
{
if (NULL != it->proc)
- it->proc (it->proc_cls, &msg->identity, attr);
+ it->proc (it->proc_cls, &msg->identity, attr, NULL, NULL);
+ }
+ else if (NULL != op)
+ {
+ if (NULL != op->ar_cb)
+ op->ar_cb (op->cls, &msg->identity, attr, NULL, NULL);
+ }
+ GNUNET_free (attr);
+ return;
+ }
+ GNUNET_assert (0);
+}
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static int
+check_attestation_result (void *cls, const struct AttributeResultMessage *msg)
+{
+ size_t msg_len;
+ size_t attr_len;
+
+ msg_len = ntohs (msg->header.size);
+ attr_len = ntohs (msg->attr_len);
+ if (msg_len != sizeof(struct AttributeResultMessage) + attr_len)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_attestation_result (void *cls, const struct AttributeResultMessage *msg)
+{
+ static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
+ struct GNUNET_RECLAIM_Handle *h = cls;
+ struct GNUNET_RECLAIM_AttributeIterator *it;
+ struct GNUNET_RECLAIM_Operation *op;
+ size_t attr_len;
+ uint32_t r_id = ntohl (msg->id);
+
+ attr_len = ntohs (msg->attr_len);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing attestation result.\n");
+
+
+ for (it = h->it_head; NULL != it; it = it->next)
+ if (it->r_id == r_id)
+ break;
+ for (op = h->op_head; NULL != op; op = op->next)
+ if (op->r_id == r_id)
+ break;
+ if ((NULL == it) && (NULL == op))
+ return;
+
+ if ((0 ==
+ (memcmp (&msg->identity, &identity_dummy, sizeof(identity_dummy)))))
+ {
+ if ((NULL == it) && (NULL == op))
+ {
+ GNUNET_break (0);
+ force_reconnect (h);
+ return;
+ }
+ if (NULL != it)
+ {
+ if (NULL != it->finish_cb)
+ it->finish_cb (it->finish_cb_cls);
+ free_it (it);
+ }
+ if (NULL != op)
+ {
+ if (NULL != op->ar_cb)
+ op->ar_cb (op->cls, NULL, NULL, NULL, NULL);
+ GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
+ free_op (op);
+ }
+ return;
+ }
+
+ {
+ struct GNUNET_RECLAIM_ATTESTATION_Claim *attr;
+ attr = GNUNET_RECLAIM_ATTESTATION_deserialize ((char *) &msg[1], attr_len);
+ if (NULL != it)
+ {
+ if (NULL != it->proc)
+ it->proc (it->proc_cls, &msg->identity, NULL, attr, NULL);
}
else if (NULL != op)
{
if (NULL != op->ar_cb)
- op->ar_cb (op->cls, &msg->identity, attr);
+ op->ar_cb (op->cls, &msg->identity, NULL, attr, NULL);
}
GNUNET_free (attr);
return;
@@ -623,6 +736,110 @@ handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
GNUNET_assert (0);
}
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static int
+check_reference_result (void *cls, const struct ReferenceResultMessage *msg)
+{
+ size_t msg_len;
+ size_t attr_len;
+ size_t ref_len;
+
+ msg_len = ntohs (msg->header.size);
+ attr_len = ntohs (msg->attest_len);
+ ref_len = ntohs (msg->ref_len);
+ if (msg_len != sizeof(struct ReferenceResultMessage) + attr_len + ref_len)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+/**
+* Handle an incoming message of type
+* #GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_RESULT
+*
+* @param cls
+* @param msg the message we received
+*/
+static void
+handle_reference_result (void *cls, const struct ReferenceResultMessage *msg)
+{
+ static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
+ struct GNUNET_RECLAIM_Handle *h = cls;
+ struct GNUNET_RECLAIM_AttributeIterator *it;
+ struct GNUNET_RECLAIM_Operation *op;
+ size_t attest_len;
+ size_t ref_len;
+ uint32_t r_id = ntohl (msg->id);
+ attest_len = ntohs (msg->attest_len);
+ ref_len = ntohs (msg->ref_len);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing reference result.\n");
+ for (it = h->it_head; NULL != it; it = it->next)
+ if (it->r_id == r_id)
+ break;
+ for (op = h->op_head; NULL != op; op = op->next)
+ if (op->r_id == r_id)
+ break;
+ if ((NULL == it) && (NULL == op))
+ return;
+
+ if ((0 ==
+ (memcmp (&msg->identity, &identity_dummy, sizeof(identity_dummy)))))
+ {
+ if ((NULL == it) && (NULL == op))
+ {
+ GNUNET_break (0);
+ force_reconnect (h);
+ return;
+ }
+ if (NULL != it)
+ {
+ if (NULL != it->finish_cb)
+ it->finish_cb (it->finish_cb_cls);
+ free_it (it);
+ }
+ if (NULL != op)
+ {
+ if (NULL != op->ar_cb)
+ op->ar_cb (op->cls, NULL, NULL, NULL, NULL);
+ GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
+ free_op (op);
+ }
+ return;
+ }
+
+ {
+ struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *ref;
+ struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
+ attest = GNUNET_RECLAIM_ATTESTATION_deserialize ((char *) &msg[1],
+ attest_len);
+ ref = GNUNET_RECLAIM_ATTESTATION_REF_deserialize ((char *) &msg[1]
+ + attest_len,
+ ref_len);
+ if (NULL != it)
+ {
+ if (NULL != it->proc)
+ it->proc (it->proc_cls, &msg->identity, NULL, attest, ref);
+ }
+ else if (NULL != op)
+ {
+ if (NULL != op->ar_cb)
+ op->ar_cb (op->cls, &msg->identity, NULL, attest, ref);
+ }
+ GNUNET_free (ref);
+ GNUNET_free (attest);
+ return;
+ }
+ GNUNET_assert (0);
+}
/**
* Handle an incoming message of type
@@ -742,6 +959,14 @@ reconnect (struct GNUNET_RECLAIM_Handle *h)
GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT,
struct AttributeResultMessage,
h),
+ GNUNET_MQ_hd_var_size (attestation_result,
+ GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT,
+ struct AttributeResultMessage,
+ h),
+ GNUNET_MQ_hd_var_size (reference_result,
+ GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_RESULT,
+ struct ReferenceResultMessage,
+ h),
GNUNET_MQ_hd_fixed_size (ticket_result,
GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT,
struct TicketResultMessage,
@@ -925,6 +1150,185 @@ GNUNET_RECLAIM_attribute_delete (
return op;
}
+/**
+ * Store an attestation. If the attestation is already present,
+ * it is replaced with the new attestation.
+ *
+ * @param h handle to the re:claimID service
+ * @param pkey private key of the identity
+ * @param attr the attestation value
+ * @param exp_interval the relative expiration interval for the attestation
+ * @param cont continuation to call when done
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the request
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_attestation_store (
+ struct GNUNET_RECLAIM_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr,
+ const struct GNUNET_TIME_Relative *exp_interval,
+ GNUNET_RECLAIM_ContinuationWithStatus cont,
+ void *cont_cls)
+{
+ struct GNUNET_RECLAIM_Operation *op;
+ struct AttributeStoreMessage *sam;
+ size_t attr_len;
+
+ op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
+ op->h = h;
+ op->as_cb = cont;
+ op->cls = cont_cls;
+ op->r_id = h->r_id_gen++;
+ GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
+ attr_len = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (attr);
+ op->env = GNUNET_MQ_msg_extra (sam,
+ attr_len,
+ GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE);
+ sam->identity = *pkey;
+ sam->id = htonl (op->r_id);
+ sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
+
+ GNUNET_RECLAIM_ATTESTATION_serialize (attr, (char *) &sam[1]);
+
+ sam->attr_len = htons (attr_len);
+ if (NULL != h->mq)
+ GNUNET_MQ_send_copy (h->mq, op->env);
+ return op;
+}
+
+/**
+ * Delete an attestation. Tickets used to share this attestation are updated
+ * accordingly.
+ *
+ * @param h handle to the re:claimID service
+ * @param pkey Private key of the identity to add an attribute to
+ * @param attr The attestation
+ * @param cont Continuation to call when done
+ * @param cont_cls Closure for @a cont
+ * @return handle Used to to abort the request
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_attestation_delete (
+ struct GNUNET_RECLAIM_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+ const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr,
+ GNUNET_RECLAIM_ContinuationWithStatus cont,
+ void *cont_cls)
+{
+ struct GNUNET_RECLAIM_Operation *op;
+ struct AttributeDeleteMessage *dam;
+ size_t attr_len;
+
+ op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
+ op->h = h;
+ op->as_cb = cont;
+ op->cls = cont_cls;
+ op->r_id = h->r_id_gen++;
+ GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
+ attr_len = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (attr);
+ op->env = GNUNET_MQ_msg_extra (dam,
+ attr_len,
+ GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE);
+ dam->identity = *pkey;
+ dam->id = htonl (op->r_id);
+ GNUNET_RECLAIM_ATTESTATION_serialize (attr, (char *) &dam[1]);
+
+ dam->attr_len = htons (attr_len);
+ if (NULL != h->mq)
+ GNUNET_MQ_send_copy (h->mq, op->env);
+ return op;
+}
+
+/**
+ * Store an attestation reference. If the reference is already present,
+ * it is replaced with the new reference.
+ *
+ * @param h handle to the re:claimID service
+ * @param pkey private key of the identity
+ * @param attr the reference value
+ * @param exp_interval the relative expiration interval for the reference
+ * @param cont continuation to call when done
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the request
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_attestation_reference_store (
+ struct GNUNET_RECLAIM_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr,
+ const struct GNUNET_TIME_Relative *exp_interval,
+ GNUNET_RECLAIM_ContinuationWithStatus cont,
+ void *cont_cls)
+{
+ struct GNUNET_RECLAIM_Operation *op;
+ struct AttributeStoreMessage *sam;
+ size_t attr_len;
+ op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
+ op->h = h;
+ op->as_cb = cont;
+ op->cls = cont_cls;
+ op->r_id = h->r_id_gen++;
+ GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
+ attr_len = GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (attr);
+ op->env = GNUNET_MQ_msg_extra (sam,
+ attr_len,
+ GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_STORE);
+ sam->identity = *pkey;
+ sam->id = htonl (op->r_id);
+ sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
+
+ GNUNET_RECLAIM_ATTESTATION_REF_serialize (attr, (char *) &sam[1]);
+
+ sam->attr_len = htons (attr_len);
+ if (NULL != h->mq)
+ GNUNET_MQ_send_copy (h->mq, op->env);
+ return op;
+}
+
+/**
+ * Delete an attestation reference. Tickets used to share this reference are updated
+ * accordingly.
+ *
+ * @param h handle to the re:claimID service
+ * @param pkey Private key of the identity to delete the reference from
+ * @param attr The reference
+ * @param cont Continuation to call when done
+ * @param cont_cls Closure for @a cont
+ * @return handle Used to to abort the request
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_attestation_reference_delete (
+ struct GNUNET_RECLAIM_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+ const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr,
+ GNUNET_RECLAIM_ContinuationWithStatus cont,
+ void *cont_cls)
+{
+
+ struct GNUNET_RECLAIM_Operation *op;
+ struct AttributeDeleteMessage *dam;
+ size_t attr_len;
+
+ op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
+ op->h = h;
+ op->as_cb = cont;
+ op->cls = cont_cls;
+ op->r_id = h->r_id_gen++;
+ GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
+ attr_len = GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (attr);
+ op->env = GNUNET_MQ_msg_extra (dam,
+ attr_len,
+ GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_DELETE);
+ dam->identity = *pkey;
+ dam->id = htonl (op->r_id);
+ GNUNET_RECLAIM_ATTESTATION_REF_serialize (attr, (char *) &dam[1]);
+
+ dam->attr_len = htons (attr_len);
+ if (NULL != h->mq)
+ GNUNET_MQ_send_copy (h->mq, op->env);
+ return op;
+}
/**
* List all attributes for a local identity.
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index c37a34ab7..077c0409a 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -1527,15 +1527,15 @@ test_transport_api_slow_ats_peer2.conf \
tcp_server_mst_legacy.c \
tcp_server_legacy.c \
tcp_service_legacy.c \
-test_communicator_basic_unix_peer1.conf \
-test_communicator_basic_unix_peer2.conf \
-test_communicator_basic_tcp_peer1.conf \
-test_communicator_basic_tcp_peer2.conf \
-test_communicator_basic_udp_peer1.conf \
-test_communicator_basic_udp_peer2.conf \
-test_communicator_rekey_tcp_peer1.conf \
-test_communicator_rekey_tcp_peer2.conf \
-test_communicator_rekey_udp_peer1.conf \
-test_communicator_rekey_udp_peer2.conf \
-test_communicator_backchannel_udp_peer1.conf \
-test_communicator_backchannel_udp_peer2.conf
+test_communicator_unix_basic_peer1.conf \
+test_communicator_unix_basic_peer2.conf \
+test_communicator_tcp_basic_peer1.conf \
+test_communicator_tcp_basic_peer2.conf \
+test_communicator_udp_basic_peer1.conf \
+test_communicator_udp_basic_peer2.conf \
+test_communicator_tcp_rekey_peer1.conf \
+test_communicator_tcp_rekey_peer2.conf \
+test_communicator_udp_rekey_peer1.conf \
+test_communicator_udp_rekey_peer2.conf \
+test_communicator_udp_backchannel_peer1.conf \
+test_communicator_udp_backchannel_peer2.conf
diff --git a/src/transport/test_communicator_unix_peer1.conf b/src/transport/test_communicator_unix_basic_peer1.conf
index d50588007..d50588007 100644
--- a/src/transport/test_communicator_unix_peer1.conf
+++ b/src/transport/test_communicator_unix_basic_peer1.conf
diff --git a/src/util/.gitignore b/src/util/.gitignore
index 01ebcc834..84c13708e 100644
--- a/src/util/.gitignore
+++ b/src/util/.gitignore
@@ -1,6 +1,7 @@
test_common_logging_dummy
gnunet-config
gnunet-config-diff
+gnunet-crypto-tvg
gnunet-ecc
gnunet-qr
gnunet-resolver
@@ -30,6 +31,7 @@ test_container_multihashmap32
test_container_multipeermap
test_crypto_crc
test_crypto_ecc_dlog
+test_crypto_ecdh_ecdsa
test_crypto_ecdh_eddsa
test_crypto_ecdhe
test_crypto_ecdsa
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 0f6251f96..fc8f424dc 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -39,6 +39,7 @@ libgnunetutil_la_SOURCES = \
bandwidth.c \
$(BENCHMARK) \
bio.c \
+ buffer.c \
client.c \
common_allocation.c \
common_endian.c \
@@ -138,41 +139,11 @@ libgnunetutil_la_LDFLAGS = \
$(GN_LIB_LDFLAGS) \
-version-info 13:2:0
-libgnunetutil_taler_wallet_la_SOURCES = \
- common_allocation.c \
- common_endian.c \
- common_logging.c \
- container_heap.c \
- container_multihashmap.c \
- container_multihashmap32.c \
- crypto_symmetric.c \
- crypto_crc.c \
- crypto_ecc.c \
- crypto_hash.c \
- crypto_hkdf.c \
- crypto_kdf.c \
- crypto_mpi.c \
- crypto_random.c \
- crypto_rsa.c \
- strings.c \
- time.c
-
-libgnunetutil_taler_wallet_la_LIBADD = \
- $(LIBGCRYPT_LIBS) \
- -lunistring
-
-libgnunetutil_taler_wallet_la_LDFLAGS = \
- $(GN_LIB_LDFLAGS) \
- -version-info 0:0:0
-
if HAVE_TESTING
GNUNET_ECC = gnunet-ecc
GNUNET_SCRYPT = gnunet-scrypt
endif
-if TALER_ONLY
-lib_LTLIBRARIES = libgnunetutil_taler_wallet.la
-else
lib_LTLIBRARIES = libgnunetutil.la
libexec_PROGRAMS = \
@@ -182,6 +153,7 @@ libexec_PROGRAMS = \
bin_PROGRAMS = \
gnunet-resolver \
gnunet-config \
+ gnunet-crypto-tvg \
$(GNUNET_ECC) \
$(GNUNET_SCRYPT) \
gnunet-uri
@@ -199,8 +171,6 @@ AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PAT
TESTS = $(check_PROGRAMS)
endif
-endif
-
gnunet_timeout_SOURCES = \
gnunet-timeout.c
@@ -220,6 +190,11 @@ gnunet_resolver_LDADD = \
libgnunetutil.la \
$(GN_LIBINTL)
+gnunet_crypto_tvg_SOURCES = \
+ gnunet-crypto-tvg.c
+gnunet_crypto_tvg_LDADD = \
+ libgnunetutil.la \
+ $(GN_LIBINTL) -lgcrypt
gnunet_ecc_SOURCES = \
gnunet-ecc.c
@@ -298,6 +273,7 @@ check_PROGRAMS = \
test_crypto_eddsa \
test_crypto_ecdhe \
test_crypto_ecdh_eddsa \
+ test_crypto_ecdh_ecdsa \
test_crypto_ecc_dlog \
test_crypto_hash \
test_crypto_hash_context \
@@ -476,6 +452,13 @@ test_crypto_ecdh_eddsa_LDADD = \
libgnunetutil.la \
$(LIBGCRYPT_LIBS)
+test_crypto_ecdh_ecdsa_SOURCES = \
+ test_crypto_ecdh_ecdsa.c
+test_crypto_ecdh_ecdsa_LDADD = \
+ libgnunetutil.la \
+ $(LIBGCRYPT_LIBS)
+
+
test_crypto_hash_SOURCES = \
test_crypto_hash.c
test_crypto_hash_LDADD = \
diff --git a/src/util/buffer.c b/src/util/buffer.c
new file mode 100644
index 000000000..d89565d68
--- /dev/null
+++ b/src/util/buffer.c
@@ -0,0 +1,226 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2020 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ GNUnet; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file buffer.c
+ * @brief Common buffer management functions.
+ * @author Florian Dold
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_buffer_lib.h"
+
+/**
+ * Initialize a buffer with the given capacity.
+ *
+ * When a buffer is allocated with this function, a warning is logged
+ * when the buffer exceeds the initial capacity.
+ *
+ * @param buf the buffer to initialize
+ * @param capacity the capacity (in bytes) to allocate for @a buf
+ */
+void
+GNUNET_buffer_prealloc (struct GNUNET_Buffer *buf, size_t capacity)
+{
+ /* Buffer should be zero-initialized */
+ GNUNET_assert (0 == buf->mem);
+ GNUNET_assert (0 == buf->capacity);
+ GNUNET_assert (0 == buf->position);
+ buf->mem = GNUNET_malloc (capacity);
+ buf->capacity = capacity;
+ buf->warn_grow = GNUNET_YES;
+}
+
+
+/**
+ * Make sure that at least @a n bytes remaining in the buffer.
+ *
+ * @param buf buffer to potentially grow
+ * @param n number of bytes that should be available to write
+ */
+void
+GNUNET_buffer_ensure_remaining (struct GNUNET_Buffer *buf, size_t n)
+{
+ size_t new_capacity = buf->position + n;
+
+ if (new_capacity <= buf->capacity)
+ return;
+ /* warn if calculation of expected size was wrong */
+ GNUNET_break (GNUNET_YES != buf->warn_grow);
+ if (new_capacity < buf->capacity * 2)
+ new_capacity = buf->capacity * 2;
+ buf->capacity = new_capacity;
+ if (NULL != buf->mem)
+ buf->mem = GNUNET_realloc (buf->mem, new_capacity);
+ else
+ buf->mem = GNUNET_malloc (new_capacity);
+}
+
+
+/**
+ * Write bytes to the buffer.
+ *
+ * Grows the buffer if necessary.
+ *
+ * @param buf buffer to write to
+ * @param data data to read from
+ * @param len number of bytes to copy from @a data to @a buf
+ *
+ */
+void
+GNUNET_buffer_write (struct GNUNET_Buffer *buf, const char *data, size_t len)
+{
+ GNUNET_buffer_ensure_remaining (buf, len);
+ memcpy (buf->mem + buf->position, data, len);
+ buf->position += len;
+}
+
+
+/**
+ * Write a 0-terminated string to a buffer, excluding the 0-terminator.
+ *
+ * @param buf the buffer to write to
+ * @param str the string to write to @a buf
+ */
+void
+GNUNET_buffer_write_str (struct GNUNET_Buffer *buf, const char *str)
+{
+ size_t len = strlen (str);
+
+ GNUNET_buffer_write (buf, str, len);
+}
+
+
+/**
+ * Clear the buffer and return the string it contained.
+ * The caller is responsible to eventually #GNUNET_free
+ * the returned string.
+ *
+ * The returned string is always 0-terminated.
+ *
+ * @param buf the buffer to reap the string from
+ * @returns the buffer contained in the string
+ */
+char *
+GNUNET_buffer_reap_str (struct GNUNET_Buffer *buf)
+{
+ char *res;
+
+ /* ensure 0-termination */
+ if ( (0 == buf->position) || ('\0' != buf->mem[buf->position - 1]))
+ {
+ GNUNET_buffer_ensure_remaining (buf, 1);
+ buf->mem[buf->position++] = '\0';
+ }
+ res = buf->mem;
+ *buf = (struct GNUNET_Buffer) { 0 };
+ return res;
+}
+
+
+/**
+ * Free the backing memory of the given buffer.
+ * Does not free the memory of the buffer control structure,
+ * which is typically stack-allocated.
+ */
+void
+GNUNET_buffer_clear (struct GNUNET_Buffer *buf)
+{
+ GNUNET_free_non_null (buf->mem);
+ *buf = (struct GNUNET_Buffer) { 0 };
+}
+
+
+/**
+ * Write a path component to a buffer, ensuring that
+ * there is exactly one slash between the previous contents
+ * of the buffer and the new string.
+ *
+ * @param buf buffer to write to
+ * @param str string containing the new path component
+ */
+void
+GNUNET_buffer_write_path (struct GNUNET_Buffer *buf, const char *str)
+{
+ size_t len = strlen (str);
+
+ while ( (0 != len) && ('/' == str[0]) )
+ {
+ str++;
+ len--;
+ }
+ if ( (0 == buf->position) || ('/' != buf->mem[buf->position - 1]) )
+ {
+ GNUNET_buffer_ensure_remaining (buf, 1);
+ buf->mem[buf->position++] = '/';
+ }
+ GNUNET_buffer_write (buf, str, len);
+}
+
+
+/**
+ * Write a 0-terminated formatted string to a buffer, excluding the
+ * 0-terminator.
+ *
+ * Grows the buffer if necessary.
+ *
+ * @param buf the buffer to write to
+ * @param fmt format string
+ * @param ... format arguments
+ */
+void
+GNUNET_buffer_write_fstr (struct GNUNET_Buffer *buf, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start (args, fmt);
+ GNUNET_buffer_write_vfstr (buf, fmt, args);
+ va_end (args);
+}
+
+
+/**
+ * Write a 0-terminated formatted string to a buffer, excluding the
+ * 0-terminator.
+ *
+ * Grows the buffer if necessary.
+ *
+ * @param buf the buffer to write to
+ * @param fmt format string
+ * @param args format argument list
+ */
+void
+GNUNET_buffer_write_vfstr (struct GNUNET_Buffer *buf,
+ const char *fmt,
+ va_list args)
+{
+ int res;
+ va_list args2;
+
+ va_copy (args2, args);
+ res = vsnprintf (NULL, 0, fmt, args2);
+ va_end (args2);
+
+ GNUNET_assert (res >= 0);
+ GNUNET_buffer_ensure_remaining (buf, res + 1);
+
+ va_copy (args2, args);
+ res = vsnprintf (buf->mem + buf->position, res + 1, fmt, args2);
+ va_end (args2);
+
+ GNUNET_assert (res >= 0);
+ buf->position += res;
+ GNUNET_assert (buf->position <= buf->capacity);
+}
diff --git a/src/util/common_logging.c b/src/util/common_logging.c
index 430f75e70..27ac88a05 100644
--- a/src/util/common_logging.c
+++ b/src/util/common_logging.c
@@ -294,7 +294,6 @@ resize_logdefs ()
}
-#if ! TALER_WALLET_ONLY
/**
* Rotate logs, deleting the oldest log.
*
@@ -403,9 +402,6 @@ setup_log_file (const struct tm *tm)
}
-#endif
-
-
/**
* Utility function - adds a parsed definition to logdefs array.
*
@@ -731,7 +727,7 @@ GNUNET_log_setup (const char *comp, const char *loglevel, const char *logfile)
log_file_name = GNUNET_STRINGS_filename_expand (logfile);
if (NULL == log_file_name)
return GNUNET_SYSERR;
-#if TALER_WALLET_ONLY || defined(GNUNET_CULL_LOGGING)
+#if defined(GNUNET_CULL_LOGGING)
/* log file option not allowed for wallet logic */
GNUNET_assert (NULL == logfile);
return GNUNET_OK;
@@ -1023,7 +1019,7 @@ mylog (enum GNUNET_ErrorType kind,
}
vsnprintf (buf, size, message, va);
-#if ! (defined(GNUNET_CULL_LOGGING) || TALER_WALLET_ONLY)
+#if ! defined(GNUNET_CULL_LOGGING)
if (NULL != tmptr)
(void) setup_log_file (tmptr);
#endif
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c
index bd7c425d4..237062eb7 100644
--- a/src/util/crypto_ecc.c
+++ b/src/util/crypto_ecc.c
@@ -173,22 +173,8 @@ GNUNET_CRYPTO_ecdsa_key_get_public (
const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
{
- gcry_sexp_t sexp;
- gcry_ctx_t ctx;
- gcry_mpi_t q;
-
BENCHMARK_START (ecdsa_key_get_public);
-
- sexp = decode_private_ecdsa_key (priv);
- GNUNET_assert (NULL != sexp);
- GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
- gcry_sexp_release (sexp);
- q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
- GNUNET_assert (NULL != q);
- GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof(pub->q_y), q);
- gcry_mpi_release (q);
- gcry_ctx_release (ctx);
-
+ GNUNET_TWEETNACL_scalarmult_gnunet_ecdsa (pub->q_y, priv->d);
BENCHMARK_END (ecdsa_key_get_public);
}
@@ -1041,45 +1027,6 @@ GNUNET_CRYPTO_ecdsa_public_key_derive (
/**
- * Take point from ECDH and convert it to key material.
- *
- * @param result point from ECDH
- * @param ctx ECC context
- * @param key_material[out] set to derived key material
- * @return #GNUNET_OK on success
- */
-static int
-point_to_hash (gcry_mpi_point_t result,
- gcry_ctx_t ctx,
- struct GNUNET_HashCode *key_material)
-{
- gcry_mpi_t result_x;
- unsigned char xbuf[256 / 8];
- size_t rsize;
-
- /* finally, convert point to string for hashing */
- result_x = gcry_mpi_new (256);
- if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
- {
- LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
- return GNUNET_SYSERR;
- }
-
- rsize = sizeof(xbuf);
- GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
- /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
- as that does not include the sign bit; x should be a 255-bit
- value, so with the sign it should fit snugly into the 256-bit
- xbuf */
- GNUNET_assert (
- 0 == gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize, result_x));
- GNUNET_CRYPTO_hash (xbuf, rsize, key_material);
- gcry_mpi_release (result_x);
- return GNUNET_OK;
-}
-
-
-/**
* @ingroup crypto
* Derive key material from a ECDH public key and a private EdDSA key.
* Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
@@ -1125,41 +1072,18 @@ GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
struct GNUNET_HashCode *key_material)
{
- gcry_mpi_point_t result;
- gcry_mpi_point_t q;
- gcry_mpi_t d;
- gcry_ctx_t ctx;
- gcry_sexp_t pub_sexpr;
- int ret;
+ uint8_t p[GNUNET_TWEETNACL_SCALARMULT_BYTES];
+ uint8_t d_rev[GNUNET_TWEETNACL_SCALARMULT_BYTES];
BENCHMARK_START (ecdsa_ecdh);
-
- /* first, extract the q = dP value from the public key */
- if (0 != gcry_sexp_build (&pub_sexpr,
- NULL,
- "(public-key(ecc(curve " CURVE ")(q %b)))",
- (int) sizeof(pub->q_y),
- pub->q_y))
- return GNUNET_SYSERR;
- GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
- gcry_sexp_release (pub_sexpr);
- q = gcry_mpi_ec_get_point ("q", ctx, 0);
-
- /* second, extract the d value from our private key */
- GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof(priv->d));
-
- /* then call the 'multiply' function, to compute the product */
- result = gcry_mpi_point_new (0);
- gcry_mpi_ec_mul (result, d, q, ctx);
- gcry_mpi_point_release (q);
- gcry_mpi_release (d);
-
- /* finally, convert point to string for hashing */
- ret = point_to_hash (result, ctx, key_material);
- gcry_mpi_point_release (result);
- gcry_ctx_release (ctx);
+ for (size_t i = 0; i < 32; i++)
+ d_rev[i] = priv->d[31 - i];
+ GNUNET_TWEETNACL_scalarmult_curve25519 (p, d_rev, pub->q_y);
+ GNUNET_CRYPTO_hash (p,
+ GNUNET_TWEETNACL_SCALARMULT_BYTES,
+ key_material);
BENCHMARK_END (ecdsa_ecdh);
- return ret;
+ return GNUNET_OK;
}
@@ -1191,7 +1115,7 @@ GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
/**
* @ingroup crypto
* Derive key material from a ECDSA public key and a private ECDH key.
- * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
+ * Dual to #GNUNET_CRYPTO_ecdsa_ecdh.
*
* @param priv private key to use for the ECDH (y)
* @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
@@ -1203,10 +1127,13 @@ GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
struct GNUNET_HashCode *key_material)
{
- return GNUNET_CRYPTO_ecdh_eddsa (priv,
- (const struct GNUNET_CRYPTO_EddsaPublicKey *)
- pub,
- key_material);
+ uint8_t p[GNUNET_TWEETNACL_SCALARMULT_BYTES];
+ uint8_t curve25510_pk[GNUNET_TWEETNACL_SIGN_PUBLICBYTES];
+
+ GNUNET_TWEETNACL_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y);
+ GNUNET_TWEETNACL_scalarmult_curve25519 (p, priv->d, curve25510_pk);
+ GNUNET_CRYPTO_hash (p, GNUNET_TWEETNACL_SCALARMULT_BYTES, key_material);
+ return GNUNET_OK;
}
diff --git a/src/util/gnunet-crypto-tvg.c b/src/util/gnunet-crypto-tvg.c
new file mode 100644
index 000000000..7d151c10b
--- /dev/null
+++ b/src/util/gnunet-crypto-tvg.c
@@ -0,0 +1,278 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2020 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file util/gnunet-crypto-tgv.c
+ * @brief Generate test vectors for cryptographic operations.
+ * @author Florian Dold
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_signatures.h"
+#include "gnunet_testing_lib.h"
+#include <gcrypt.h>
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Sample signature struct.
+ *
+ * Purpose is #GNUNET_SIGNATURE_PURPOSE_TEST
+ */
+struct TestSignatureDataPS
+{
+ struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+ uint32_t testval;
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+
+/**
+ * Print data base32-crockford with a preceding label.
+ *
+ * @param label label to print
+ * @param data data to print
+ * @param size size of data
+ */
+static void
+display_data (char *label, void *data, size_t size)
+{
+ char *enc = GNUNET_STRINGS_data_to_string_alloc (data, size);
+ printf ("%s %s\n", label, enc);
+ GNUNET_free (enc);
+}
+
+
+/**
+ * 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 cfg configuration
+ */
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ {
+ struct GNUNET_HashCode hc;
+ char *str = "Hello, GNUnet";
+
+ GNUNET_CRYPTO_hash (str, strlen (str), &hc);
+
+ printf ("hash code:\n");
+ display_data (" input", str, strlen (str));
+ display_data (" output", &hc, sizeof (struct GNUNET_HashCode));
+ }
+ {
+ struct GNUNET_CRYPTO_EcdhePrivateKey *priv1;
+ struct GNUNET_CRYPTO_EcdhePublicKey pub1;
+ struct GNUNET_CRYPTO_EcdhePrivateKey *priv2;
+ struct GNUNET_HashCode skm;
+ priv1 = GNUNET_CRYPTO_ecdhe_key_create ();
+ priv2 = GNUNET_CRYPTO_ecdhe_key_create ();
+ GNUNET_CRYPTO_ecdhe_key_get_public (priv1, &pub1);
+ GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecc_ecdh (priv2, &pub1, &skm));
+
+ printf ("ecdhe key:\n");
+ display_data (" priv1", priv1, sizeof (struct
+ GNUNET_CRYPTO_EcdhePrivateKey));
+ display_data (" pub1", &pub1, sizeof (struct
+ GNUNET_CRYPTO_EcdhePublicKey));
+ display_data (" priv2", priv2, sizeof (struct
+ GNUNET_CRYPTO_EcdhePrivateKey));
+ display_data (" skm", &skm, sizeof (struct GNUNET_HashCode));
+ GNUNET_free (priv1);
+ GNUNET_free (priv2);
+ }
+
+ {
+ struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
+ struct GNUNET_CRYPTO_EddsaPublicKey pub;
+ priv = GNUNET_CRYPTO_eddsa_key_create ();
+ GNUNET_CRYPTO_eddsa_key_get_public (priv, &pub);
+
+ printf ("eddsa key:\n");
+ display_data (" priv", priv, sizeof (struct
+ GNUNET_CRYPTO_EddsaPrivateKey));
+ display_data (" pub", &pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
+ GNUNET_free (priv);
+ }
+ {
+ struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
+ struct GNUNET_CRYPTO_EddsaPublicKey pub;
+ struct GNUNET_CRYPTO_EddsaSignature sig;
+ struct TestSignatureDataPS data = { 0 };
+ priv = GNUNET_CRYPTO_eddsa_key_create ();
+ GNUNET_CRYPTO_eddsa_key_get_public (priv, &pub);
+ data.purpose.size = htonl (sizeof (struct TestSignatureDataPS));
+ data.purpose.size = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
+ GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (priv, &data.purpose,
+ &sig));
+ GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_verify (0,
+ &data.purpose,
+ &sig,
+ &pub));
+
+ printf ("eddsa sig:\n");
+ display_data (" priv", priv, sizeof (struct
+ GNUNET_CRYPTO_EddsaPrivateKey));
+ display_data (" pub", &pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
+ display_data (" data", &data, sizeof (struct TestSignatureDataPS));
+ display_data (" sig", &sig, sizeof (struct GNUNET_CRYPTO_EddsaSignature));
+ GNUNET_free (priv);
+ }
+
+ {
+ size_t out_len = 64;
+ char out[out_len];
+ char *ikm = "I'm the secret input key material";
+ char *salt = "I'm very salty";
+ char *ctx = "I'm a context chunk, also known as 'info' in the RFC";
+
+ GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_kdf (&out,
+ out_len,
+ salt,
+ strlen (salt),
+ ikm,
+ strlen (ikm),
+ ctx,
+ strlen (ctx),
+ NULL));
+
+ printf ("kdf:\n");
+ display_data (" salt", salt, strlen (salt));
+ display_data (" ikm", ikm, strlen (ikm));
+ display_data (" ctx", ctx, strlen (ctx));
+ printf (" out_len %u\n", (unsigned int) out_len);
+ display_data (" out", out, out_len);
+ }
+ {
+ struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ecdhe;
+ struct GNUNET_CRYPTO_EcdhePublicKey pub_ecdhe;
+ struct GNUNET_CRYPTO_EddsaPrivateKey *priv_eddsa;
+ struct GNUNET_CRYPTO_EddsaPublicKey pub_eddsa;
+ struct GNUNET_HashCode key_material;
+ priv_ecdhe = GNUNET_CRYPTO_ecdhe_key_create ();
+ GNUNET_CRYPTO_ecdhe_key_get_public (priv_ecdhe, &pub_ecdhe);
+ priv_eddsa = GNUNET_CRYPTO_eddsa_key_create ();
+ GNUNET_CRYPTO_eddsa_key_get_public (priv_eddsa, &pub_eddsa);
+ GNUNET_CRYPTO_ecdh_eddsa (priv_ecdhe, &pub_eddsa, &key_material);
+
+ printf ("eddsa_ecdh:\n");
+ display_data (" priv_ecdhe", priv_ecdhe, sizeof (struct
+ GNUNET_CRYPTO_EcdhePrivateKey));
+ display_data (" pub_ecdhe", &pub_ecdhe, sizeof (struct
+ GNUNET_CRYPTO_EcdhePublicKey));
+ display_data (" priv_eddsa", priv_eddsa, sizeof (struct
+ GNUNET_CRYPTO_EddsaPrivateKey));
+ display_data (" pub_eddsa", &pub_eddsa, sizeof (struct
+ GNUNET_CRYPTO_EddsaPublicKey));
+ display_data (" key_material", &key_material, sizeof (struct
+ GNUNET_HashCode));
+ }
+
+ {
+ struct GNUNET_CRYPTO_RsaPrivateKey *skey;
+ struct GNUNET_CRYPTO_RsaPublicKey *pkey;
+ struct GNUNET_HashCode message_hash;
+ struct GNUNET_CRYPTO_RsaBlindingKeySecret bks;
+ struct GNUNET_CRYPTO_RsaSignature *blinded_sig;
+ struct GNUNET_CRYPTO_RsaSignature *sig;
+ char *blinded_data;
+ size_t blinded_len;
+ char *public_enc_data;
+ size_t public_enc_len;
+ char *blinded_sig_enc_data;
+ size_t blinded_sig_enc_length;
+ char *sig_enc_data;
+ size_t sig_enc_length;
+ skey = GNUNET_CRYPTO_rsa_private_key_create (2048);
+ pkey = GNUNET_CRYPTO_rsa_private_key_get_public (skey);
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, &message_hash,
+ sizeof (struct GNUNET_HashCode));
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, &bks, sizeof (struct
+ GNUNET_CRYPTO_RsaBlindingKeySecret));
+ GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_rsa_blind (&message_hash, &bks,
+ pkey, &blinded_data,
+ &blinded_len));
+ blinded_sig = GNUNET_CRYPTO_rsa_sign_blinded (skey, blinded_data,
+ blinded_len);
+ sig = GNUNET_CRYPTO_rsa_unblind (blinded_sig, &bks, pkey);
+ GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_rsa_verify (&message_hash, sig,
+ pkey));
+ public_enc_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey,
+ &public_enc_data);
+ blinded_sig_enc_length = GNUNET_CRYPTO_rsa_signature_encode (blinded_sig,
+ &
+ blinded_sig_enc_data);
+ sig_enc_length = GNUNET_CRYPTO_rsa_signature_encode (sig, &sig_enc_data);
+ printf ("blind signing:\n");
+ display_data (" message_hash", &message_hash, sizeof (struct
+ GNUNET_HashCode));
+ display_data (" rsa_public_key", public_enc_data, public_enc_len);
+ display_data (" blinding_key_secret", &bks, sizeof (struct
+ GNUNET_CRYPTO_RsaBlindingKeySecret));
+ display_data (" blinded_message", blinded_data, blinded_len);
+ display_data (" blinded_sig", blinded_sig_enc_data,
+ blinded_sig_enc_length);
+ display_data (" sig", sig_enc_data, sig_enc_length);
+ GNUNET_CRYPTO_rsa_private_key_free (skey);
+ GNUNET_CRYPTO_rsa_public_key_free (pkey);
+ GNUNET_CRYPTO_rsa_signature_free (sig);
+ GNUNET_CRYPTO_rsa_signature_free (blinded_sig);
+ }
+}
+
+
+/**
+ * The main function of the test vector generation tool.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc,
+ char *const *argv)
+{
+ const struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_log_setup ("gnunet-crypto-tvg",
+ "INFO",
+ NULL));
+ if (GNUNET_OK !=
+ GNUNET_PROGRAM_run (argc, argv,
+ "gnunet-crypto-tvg",
+ "Generate test vectors for cryptographic operations",
+ options,
+ &run, NULL))
+ return 1;
+ return 0;
+}
+
+/* end of gnunet-crypto-tvg.c */
diff --git a/src/util/test_crypto_ecdh_ecdsa.c b/src/util/test_crypto_ecdh_ecdsa.c
new file mode 100644
index 000000000..8a581ef73
--- /dev/null
+++ b/src/util/test_crypto_ecdh_ecdsa.c
@@ -0,0 +1,97 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2002-2015 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+
+ */
+/**
+ * @file util/test_crypto_ecdh_ecdsa.c
+ * @brief testcase for ECC DH key exchange with ECDSA private keys.
+ * @author Christian Grothoff
+ * @author Bart Polot
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include <gcrypt.h>
+
+
+static int
+test_ecdh ()
+{
+ struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_dsa;
+ struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ecdh;
+ struct GNUNET_CRYPTO_EcdsaPublicKey id1;
+ struct GNUNET_CRYPTO_EcdhePublicKey id2;
+ struct GNUNET_HashCode dh[2];
+
+ /* Generate keys */
+ priv_dsa = GNUNET_CRYPTO_ecdsa_key_create ();
+ GNUNET_CRYPTO_ecdsa_key_get_public (priv_dsa,
+ &id1);
+ for (unsigned int j = 0; j < 4; j++)
+ {
+ fprintf (stderr, ",");
+ priv_ecdh = GNUNET_CRYPTO_ecdhe_key_create ();
+ /* Extract public keys */
+ GNUNET_CRYPTO_ecdhe_key_get_public (priv_ecdh,
+ &id2);
+ /* Do ECDH */
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_ecdsa_ecdh (priv_dsa,
+ &id2,
+ &dh[0]));
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_ecdh_ecdsa (priv_ecdh,
+ &id1,
+ &dh[1]));
+ /* Check that both DH results are equal. */
+ GNUNET_assert (0 == memcmp (&dh[0],
+ &dh[1],
+ sizeof(struct GNUNET_HashCode)));
+ GNUNET_free (priv_ecdh);
+ }
+ GNUNET_free (priv_dsa);
+ return 0;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ if (! gcry_check_version ("1.6.0"))
+ {
+ fprintf (stderr,
+ _ (
+ "libgcrypt has not the expected version (version %s is required).\n"),
+ "1.6.0");
+ return 0;
+ }
+ if (getenv ("GNUNET_GCRYPT_DEBUG"))
+ gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+ GNUNET_log_setup ("test-crypto-ecdh-ecdsa", "WARNING", NULL);
+ for (unsigned int i = 0; i < 4; i++)
+ {
+ fprintf (stderr,
+ ".");
+ if (0 != test_ecdh ())
+ return 1;
+ }
+ return 0;
+}
+
+
+/* end of test_crypto_ecdh_ecdsa.c */
diff --git a/src/util/tweetnacl-gnunet.c b/src/util/tweetnacl-gnunet.c
index 1c27730a4..f01667adb 100644
--- a/src/util/tweetnacl-gnunet.c
+++ b/src/util/tweetnacl-gnunet.c
@@ -424,8 +424,24 @@ GNUNET_TWEETNACL_sign_pk_from_seed (u8 *pk, const u8 *seed)
d[31] &= 127;
d[31] |= 64;
- scalarbase (p,d);
- pack (pk,p);
+ scalarbase (p, d);
+ pack (pk, p);
+}
+
+void
+GNUNET_TWEETNACL_scalarmult_gnunet_ecdsa (u8 *pk, const u8 *s)
+{
+ u8 d[64];
+ gf p[4];
+
+ // Treat s as little endian.
+ for (u32 i = 0; i < 32; i++)
+ d[i] = s[31 - i];
+
+ // For GNUnet, we don't normalize d
+
+ scalarbase (p, d);
+ pack (pk, p);
}
void
diff --git a/src/util/tweetnacl-gnunet.h b/src/util/tweetnacl-gnunet.h
index 239166ffc..d052d8824 100644
--- a/src/util/tweetnacl-gnunet.h
+++ b/src/util/tweetnacl-gnunet.h
@@ -47,4 +47,8 @@ GNUNET_TWEETNACL_sign_detached (uint8_t *sig,
const uint8_t *m,
uint64_t n,
const uint8_t *sk);
+
+void
+GNUNET_TWEETNACL_scalarmult_gnunet_ecdsa (uint8_t *pk, const uint8_t *s);
+
#endif
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c
index 50c990b3a..62bc45e41 100644
--- a/src/vpn/gnunet-service-vpn.c
+++ b/src/vpn/gnunet-service-vpn.c
@@ -2940,7 +2940,8 @@ run (void *cls,
struct in6_addr v6;
char *binary;
- binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
+ cfg = cfg_;
+ binary = GNUNET_OS_get_suid_binary_path (cfg, "gnunet-helper-vpn");
if (GNUNET_YES !=
GNUNET_OS_check_helper_binary (
@@ -2949,8 +2950,8 @@ run (void *cls,
"-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) // ipv4 only please!
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "`%s' is not SUID, refusing to run.\n",
- "gnunet-helper-vpn");
+ "`%s' is not SUID or the path is invalid, refusing to run.\n",
+ binary);
GNUNET_free (binary);
global_ret = 1;
/* we won't "really" exit here, as the 'service' is still running;
@@ -2958,8 +2959,6 @@ run (void *cls,
anything either */
return;
}
- GNUNET_free (binary);
- cfg = cfg_;
stats = GNUNET_STATISTICS_create ("vpn", cfg);
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (cfg,
@@ -2989,6 +2988,7 @@ run (void *cls,
GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
+ GNUNET_free (binary);
GNUNET_SCHEDULER_shutdown ();
return;
}
@@ -3006,6 +3006,7 @@ run (void *cls,
"VPN",
"IPV6ADDR",
_ ("Must specify valid IPv6 address"));
+ GNUNET_free (binary);
GNUNET_SCHEDULER_shutdown ();
GNUNET_free_non_null (ipv6addr);
return;
@@ -3033,6 +3034,7 @@ run (void *cls,
"VPN",
"IPV4MASK",
_ ("Must specify valid IPv6 mask"));
+ GNUNET_free (binary);
GNUNET_SCHEDULER_shutdown ();
return;
}
@@ -3058,6 +3060,7 @@ run (void *cls,
"VPN",
"IPV4ADDR",
_ ("Must specify valid IPv4 address"));
+ GNUNET_free (binary);
GNUNET_SCHEDULER_shutdown ();
GNUNET_free_non_null (ipv4addr);
return;
@@ -3074,6 +3077,7 @@ run (void *cls,
"VPN",
"IPV4MASK",
_ ("Must specify valid IPv4 mask"));
+ GNUNET_free (binary);
GNUNET_SCHEDULER_shutdown ();
GNUNET_free_non_null (ipv4mask);
return;
@@ -3093,11 +3097,12 @@ run (void *cls,
cadet_handle = GNUNET_CADET_connect (cfg_);
// FIXME never opens ports???
helper_handle = GNUNET_HELPER_start (GNUNET_NO,
- "gnunet-helper-vpn",
+ binary,
vpn_argv,
&message_token,
NULL,
NULL);
+ GNUNET_free (binary);
GNUNET_SCHEDULER_add_shutdown (&cleanup, NULL);
}