From 3d670727232e79b7e49a1df7ba9260db4e5798a0 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 16 Oct 2013 20:14:02 +0000 Subject: -moving namestore_common functions to gnsrecord library --- src/conversation/Makefile.am | 1 + src/gns/Makefile.am | 4 + src/gnsrecord/Makefile.am | 23 +- src/gnsrecord/gnsrecord_crypto.c | 263 +++++++++ src/gnsrecord/gnsrecord_misc.c | 267 +++++++++ src/gnsrecord/gnsrecord_serialization.c | 188 ++++++ src/gnsrecord/test_gnsrecord_crypto.c | 145 +++++ src/gnsrecord/test_gnsrecord_serialization.c | 140 +++++ src/include/gnunet_gnsrecord_lib.h | 354 ++++++++++++ src/include/gnunet_namestore_service.h | 348 +---------- src/namecache/Makefile.am | 5 +- src/namestore/Makefile.am | 30 +- src/namestore/namestore_api_common.c | 638 --------------------- src/namestore/test_namestore_api_blocks.c | 147 ----- .../test_namestore_record_serialization.c | 152 ----- 15 files changed, 1400 insertions(+), 1305 deletions(-) create mode 100644 src/gnsrecord/gnsrecord_crypto.c create mode 100644 src/gnsrecord/gnsrecord_misc.c create mode 100644 src/gnsrecord/gnsrecord_serialization.c create mode 100644 src/gnsrecord/test_gnsrecord_crypto.c create mode 100644 src/gnsrecord/test_gnsrecord_serialization.c delete mode 100644 src/namestore/namestore_api_common.c delete mode 100644 src/namestore/test_namestore_api_blocks.c delete mode 100644 src/namestore/test_namestore_record_serialization.c (limited to 'src') diff --git a/src/conversation/Makefile.am b/src/conversation/Makefile.am index 92a649d10..e6469c00a 100644 --- a/src/conversation/Makefile.am +++ b/src/conversation/Makefile.am @@ -52,6 +52,7 @@ libgnunetconversation_la_SOURCES = \ conversation_api.c libgnunetconversation_la_LIBADD = \ $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am index 692ac9832..6ee6d02ad 100644 --- a/src/gns/Makefile.am +++ b/src/gns/Makefile.am @@ -100,6 +100,7 @@ gnunet_gns_DEPENDENCIES = \ gnunet_dns2gns_SOURCES = \ gnunet-dns2gns.c gnunet_dns2gns_LDADD = \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ @@ -108,6 +109,7 @@ gnunet_dns2gns_LDADD = \ $(top_builddir)/src/dns/libgnunetdnsstub.la \ $(GN_LIBINTL) gnunet_dns2gns_DEPENDENCIES = \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ @@ -156,6 +158,7 @@ gnunet_service_gns_SOURCES = \ gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h gnunet_service_gns_LDADD = \ -lm \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/dns/libgnunetdns.la \ @@ -166,6 +169,7 @@ gnunet_service_gns_LDADD = \ $(USE_VPN) \ $(GN_LIBINTL) gnunet_service_gns_DEPENDENCIES = \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/dns/libgnunetdns.la \ diff --git a/src/gnsrecord/Makefile.am b/src/gnsrecord/Makefile.am index 2fb859f39..1f489c8d7 100644 --- a/src/gnsrecord/Makefile.am +++ b/src/gnsrecord/Makefile.am @@ -15,6 +15,10 @@ if USE_COVERAGE XLIBS = -lgcov endif +check_PROGRAMS = \ + test_gnsrecord_crypto \ + test_gnsrecord_serialization + if ENABLE_TEST_RUN TESTS = \ $(check_PROGRAMS) \ @@ -25,7 +29,10 @@ lib_LTLIBRARIES = \ libgnunetgnsrecord.la libgnunetgnsrecord_la_SOURCES = \ - gnsrecord.c + gnsrecord.c \ + gnsrecord_serialization.c \ + gnsrecord_crypto.c \ + gnsrecord_misc.c libgnunetgnsrecord_la_LIBADD = \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/util/libgnunetutil.la \ @@ -52,3 +59,17 @@ libgnunet_plugin_gnsrecord_dns_la_LDFLAGS = \ EXTRA_DIST = \ $(check_SCRIPTS) +test_gnsrecord_serialization_SOURCES = \ + test_gnsrecord_serialization.c +test_gnsrecord_serialization_LDADD = \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ + $(top_builddir)/src/util/libgnunetutil.la + +test_gnsrecord_crypto_SOURCES = \ + test_gnsrecord_crypto.c +test_gnsrecord_crypto_LDADD = \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ + $(top_builddir)/src/util/libgnunetutil.la + diff --git a/src/gnsrecord/gnsrecord_crypto.c b/src/gnsrecord/gnsrecord_crypto.c new file mode 100644 index 000000000..823ffcae3 --- /dev/null +++ b/src/gnsrecord/gnsrecord_crypto.c @@ -0,0 +1,263 @@ +/* + This file is part of GNUnet. + (C) 2009-2013 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file gnsrecord/gnsrecord_crypto.c + * @brief API for GNS record-related crypto + * @author Martin Schanzenbach + * @author Matthias Wachs + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_constants.h" +#include "gnunet_signatures.h" +#include "gnunet_arm_service.h" +#include "gnunet_gnsrecord_lib.h" +#include "gnunet_dnsparser_lib.h" +#include "gnunet_tun_lib.h" + + +#define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) + + +/** + * Derive session key and iv from label and public key. + * + * @param iv initialization vector to initialize + * @param skey session key to initialize + * @param label label to use for KDF + * @param pub public key to use for KDF + */ +static void +derive_block_aes_key (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, + struct GNUNET_CRYPTO_SymmetricSessionKey *skey, + const char *label, + const struct GNUNET_CRYPTO_EcdsaPublicKey *pub) +{ + static const char ctx_key[] = "gns-aes-ctx-key"; + static const char ctx_iv[] = "gns-aes-ctx-iv"; + + GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), + pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), + label, strlen (label), + ctx_key, strlen (ctx_key), + NULL, 0); + GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector), + pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), + label, strlen (label), + ctx_iv, strlen (ctx_iv), + NULL, 0); +} + + +/** + * Sign name and records + * + * @param key the private key + * @param expire block expiration + * @param label the name for the records + * @param rd record data + * @param rd_count number of records + * @return NULL on error (block too large) + */ +struct GNUNET_NAMESTORE_Block * +GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, + struct GNUNET_TIME_Absolute expire, + const char *label, + const struct GNUNET_NAMESTORE_RecordData *rd, + unsigned int rd_count) +{ + size_t payload_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd); + char payload[sizeof (uint32_t) + payload_len]; + struct GNUNET_NAMESTORE_Block *block; + struct GNUNET_CRYPTO_EcdsaPublicKey pkey; + struct GNUNET_CRYPTO_EcdsaPrivateKey *dkey; + struct GNUNET_CRYPTO_SymmetricInitializationVector iv; + struct GNUNET_CRYPTO_SymmetricSessionKey skey; + uint32_t rd_count_nbo; + + if (payload_len > GNUNET_NAMESTORE_MAX_VALUE_SIZE) + return NULL; + rd_count_nbo = htonl (rd_count); + memcpy (payload, &rd_count_nbo, sizeof (uint32_t)); + GNUNET_assert (payload_len == + GNUNET_NAMESTORE_records_serialize (rd_count, rd, + payload_len, &payload[sizeof (uint32_t)])); + block = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Block) + + sizeof (uint32_t) + payload_len); + block->purpose.size = htonl (sizeof (uint32_t) + payload_len + + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + + sizeof (struct GNUNET_TIME_AbsoluteNBO)); + block->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); + block->expiration_time = GNUNET_TIME_absolute_hton (expire); + dkey = GNUNET_CRYPTO_ecdsa_private_key_derive (key, + label, + "gns"); + GNUNET_CRYPTO_ecdsa_key_get_public (dkey, + &block->derived_key); + GNUNET_CRYPTO_ecdsa_key_get_public (key, + &pkey); + derive_block_aes_key (&iv, &skey, label, &pkey); + GNUNET_break (payload_len + sizeof (uint32_t) == + GNUNET_CRYPTO_symmetric_encrypt (payload, payload_len + sizeof (uint32_t), + &skey, &iv, + &block[1])); + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_sign (dkey, + &block->purpose, + &block->signature)) + { + GNUNET_break (0); + GNUNET_free (dkey); + GNUNET_free (block); + return NULL; + } + GNUNET_free (dkey); + return block; +} + + +/** + * Check if a signature is valid. This API is used by the GNS Block + * to validate signatures received from the network. + * + * @param block block to verify + * @return #GNUNET_OK if the signature is valid + */ +int +GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block) +{ + return GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, + &block->purpose, + &block->signature, + &block->derived_key); +} + + +/** + * Decrypt block. + * + * @param block block to decrypt + * @param zone_key public key of the zone + * @param label the name for the records + * @param proc function to call with the result + * @param proc_cls closure for proc + * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was + * not well-formed + */ +int +GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block, + const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key, + const char *label, + GNUNET_NAMESTORE_RecordCallback proc, + void *proc_cls) +{ + size_t payload_len = ntohl (block->purpose.size) - + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) - + sizeof (struct GNUNET_TIME_AbsoluteNBO); + struct GNUNET_CRYPTO_SymmetricInitializationVector iv; + struct GNUNET_CRYPTO_SymmetricSessionKey skey; + + if (ntohl (block->purpose.size) < + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + + sizeof (struct GNUNET_TIME_AbsoluteNBO)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + derive_block_aes_key (&iv, &skey, label, zone_key); + { + char payload[payload_len]; + uint32_t rd_count; + + GNUNET_break (payload_len == + GNUNET_CRYPTO_symmetric_decrypt (&block[1], payload_len, + &skey, &iv, + payload)); + memcpy (&rd_count, + payload, + sizeof (uint32_t)); + rd_count = ntohl (rd_count); + if (rd_count > 2048) + { + /* limit to sane value */ + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + { + struct GNUNET_NAMESTORE_RecordData rd[rd_count]; + + if (GNUNET_OK != + GNUNET_NAMESTORE_records_deserialize (payload_len - sizeof (uint32_t), + &payload[sizeof (uint32_t)], + rd_count, + rd)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (NULL != proc) + proc (proc_cls, rd_count, (0 != rd_count) ? rd : NULL); + } + } + return GNUNET_OK; +} + + +/** + * Calculate the DHT query for a given @a label in a given @a zone. + * + * @param zone private key of the zone + * @param label label of the record + * @param query hash to use for the query + */ +void +GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *label, + struct GNUNET_HashCode *query) +{ + struct GNUNET_CRYPTO_EcdsaPublicKey pub; + + GNUNET_CRYPTO_ecdsa_key_get_public (zone, &pub); + GNUNET_NAMESTORE_query_from_public_key (&pub, label, query); +} + + +/** + * Calculate the DHT query for a given @a label in a given @a zone. + * + * @param pub public key of the zone + * @param label label of the record + * @param query hash to use for the query + */ +void +GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, + const char *label, + struct GNUNET_HashCode *query) +{ + struct GNUNET_CRYPTO_EcdsaPublicKey pd; + + GNUNET_CRYPTO_ecdsa_public_key_derive (pub, label, "gns", &pd); + GNUNET_CRYPTO_hash (&pd, sizeof (pd), query); +} + + +/* end of gnsrecord_crypto.c */ diff --git a/src/gnsrecord/gnsrecord_misc.c b/src/gnsrecord/gnsrecord_misc.c new file mode 100644 index 000000000..7d73af376 --- /dev/null +++ b/src/gnsrecord/gnsrecord_misc.c @@ -0,0 +1,267 @@ +/* + This file is part of GNUnet. + (C) 2009-2013 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file gnsrecord/gnsrecord_misc.c + * @brief MISC functions related to GNS records + * @author Martin Schanzenbach + * @author Matthias Wachs + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_constants.h" +#include "gnunet_signatures.h" +#include "gnunet_arm_service.h" +#include "gnunet_gnsrecord_lib.h" +#include "gnunet_dnsparser_lib.h" +#include "gnunet_tun_lib.h" + + +#define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) + +/** + * Convert a UTF-8 string to UTF-8 lowercase + * @param src source string + * @return converted result + */ +char * +GNUNET_NAMESTORE_normalize_string (const char *src) +{ + GNUNET_assert (NULL != src); + char *res = strdup (src); + /* normalize */ + GNUNET_STRINGS_utf8_tolower(src, &res); + return res; +} + + +/** + * Convert a zone key to a string (for printing debug messages). + * This is one of the very few calls in the entire API that is + * NOT reentrant! + * + * @param z the zone key + * @return string form; will be overwritten by next call to #GNUNET_NAMESTORE_z2s + */ +const char * +GNUNET_NAMESTORE_z2s (const struct GNUNET_CRYPTO_EcdsaPublicKey *z) +{ + static char buf[sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) * 8]; + char *end; + + end = GNUNET_STRINGS_data_to_string ((const unsigned char *) z, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), + buf, sizeof (buf)); + if (NULL == end) + { + GNUNET_break (0); + return NULL; + } + *end = '\0'; + return buf; +} + + +/** + * Compares if two records are equal (ignoring flags such + * as authority, private and pending, but not relative vs. + * absolute expiration time). + * + * @param a record + * @param b record + * @return #GNUNET_YES if the records are equal or #GNUNET_NO if they are not + */ +int +GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a, + const struct GNUNET_NAMESTORE_RecordData *b) +{ + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Comparing records\n"); + if (a->record_type != b->record_type) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Record type %lu != %lu\n", a->record_type, b->record_type); + return GNUNET_NO; + } + if ((a->expiration_time != b->expiration_time) && + ((a->expiration_time != 0) && (b->expiration_time != 0))) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Expiration time %llu != %llu\n", + a->expiration_time, + b->expiration_time); + return GNUNET_NO; + } + if ((a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS) + != (b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS)) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Flags %lu (%lu) != %lu (%lu)\n", a->flags, + a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS, b->flags, + b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS); + return GNUNET_NO; + } + if (a->data_size != b->data_size) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Data size %lu != %lu\n", + a->data_size, + b->data_size); + return GNUNET_NO; + } + if (0 != memcmp (a->data, b->data, a->data_size)) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Data contents do not match\n"); + return GNUNET_NO; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Records are equal\n"); + return GNUNET_YES; +} + + +/** + * Returns the expiration time of the given block of records. The block + * expiration time is the expiration time of the record with smallest + * expiration time. + * + * @param rd_count number of records given in @a rd + * @param rd array of records + * @return absolute expiration time + */ +struct GNUNET_TIME_Absolute +GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + unsigned int c; + struct GNUNET_TIME_Absolute expire; + struct GNUNET_TIME_Absolute at; + struct GNUNET_TIME_Relative rt; + + if (NULL == rd) + return GNUNET_TIME_UNIT_ZERO_ABS; + expire = GNUNET_TIME_UNIT_FOREVER_ABS; + for (c = 0; c < rd_count; c++) + { + if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) + { + rt.rel_value_us = rd[c].expiration_time; + at = GNUNET_TIME_relative_to_absolute (rt); + } + else + { + at.abs_value_us = rd[c].expiration_time; + } + expire = GNUNET_TIME_absolute_min (at, expire); + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Determined expiration time for block with %u records to be %s\n", + rd_count, + GNUNET_STRINGS_absolute_time_to_string (expire)); + return expire; +} + + +/** + * Test if a given record is expired. + * + * @return #GNUNET_YES if the record is expired, + * #GNUNET_NO if not + */ +int +GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct GNUNET_TIME_Absolute at; + + if (0 != (rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) + return GNUNET_NO; + at.abs_value_us = rd->expiration_time; + return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value_us) ? GNUNET_YES : GNUNET_NO; +} + + +/** + * Convert public key to the respective absolute domain name in the + * ".zkey" pTLD. + * This is one of the very few calls in the entire API that is + * NOT reentrant! + * + * @param pkey a public key with a point on the eliptic curve + * @return string "X.zkey" where X is the public + * key in an encoding suitable for DNS labels. + */ +const char * +GNUNET_NAMESTORE_pkey_to_zkey (const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey) +{ + static char ret[128]; + char *pkeys; + + pkeys = GNUNET_CRYPTO_ecdsa_public_key_to_string (pkey); + GNUNET_snprintf (ret, + sizeof (ret), + "%s.zkey", + pkeys); + GNUNET_free (pkeys); + return ret; +} + + +/** + * Convert an absolute domain name in the ".zkey" pTLD to the + * respective public key. + * + * @param zkey string "X.zkey" where X is the coordinates of the public + * key in an encoding suitable for DNS labels. + * @param pkey set to a public key on the eliptic curve + * @return #GNUNET_SYSERR if @a zkey has the wrong syntax + */ +int +GNUNET_NAMESTORE_zkey_to_pkey (const char *zkey, + struct GNUNET_CRYPTO_EcdsaPublicKey *pkey) +{ + char *cpy; + char *dot; + const char *x; + + cpy = GNUNET_strdup (zkey); + x = cpy; + if (NULL == (dot = strchr (x, (int) '.'))) + goto error; + *dot = '\0'; + if (0 != strcasecmp (dot + 1, + "zkey")) + goto error; + + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_public_key_from_string (x, + strlen (x), + pkey)) + goto error; + GNUNET_free (cpy); + return GNUNET_OK; + error: + GNUNET_free (cpy); + return GNUNET_SYSERR; +} + + +/* end of gnsrecord_misc.c */ diff --git a/src/gnsrecord/gnsrecord_serialization.c b/src/gnsrecord/gnsrecord_serialization.c new file mode 100644 index 000000000..0fd10b3e0 --- /dev/null +++ b/src/gnsrecord/gnsrecord_serialization.c @@ -0,0 +1,188 @@ +/* + This file is part of GNUnet. + (C) 2009-2013 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file gnsrecord/gnsrecord_serialization.c + * @brief API to serialize and deserialize GNS records + * @author Martin Schanzenbach + * @author Matthias Wachs + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_constants.h" +#include "gnunet_signatures.h" +#include "gnunet_arm_service.h" +#include "gnunet_gnsrecord_lib.h" +#include "gnunet_dnsparser_lib.h" +#include "gnunet_tun_lib.h" + + +#define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) + +GNUNET_NETWORK_STRUCT_BEGIN + + +/** + * Internal format of a record in the serialized form. + */ +struct NetworkRecord +{ + + /** + * Expiration time for the DNS record; relative or absolute depends + * on 'flags', network byte order. + */ + uint64_t expiration_time GNUNET_PACKED; + + /** + * Number of bytes in 'data', network byte order. + */ + uint32_t data_size GNUNET_PACKED; + + /** + * Type of the GNS/DNS record, network byte order. + */ + uint32_t record_type GNUNET_PACKED; + + /** + * Flags for the record, network byte order. + */ + uint32_t flags GNUNET_PACKED; + +}; + +GNUNET_NETWORK_STRUCT_END + + +/** + * Calculate how many bytes we will need to serialize the given + * records. + * + * @param rd_count number of records in the rd array + * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements + * @return the required size to serialize + */ +size_t +GNUNET_NAMESTORE_records_get_size (unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + unsigned int i; + size_t ret; + + ret = sizeof (struct NetworkRecord) * rd_count; + for (i=0;i= ret); + ret += rd[i].data_size; + } + return ret; +} + + +/** + * Serialize the given records to the given destination buffer. + * + * @param rd_count number of records in the rd array + * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements + * @param dest_size size of the destination array + * @param dest where to write the result + * @return the size of serialized records, -1 if records do not fit + */ +ssize_t +GNUNET_NAMESTORE_records_serialize (unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + size_t dest_size, + char *dest) +{ + struct NetworkRecord rec; + unsigned int i; + size_t off; + + off = 0; + for (i=0;i dest_size) + return -1; + memcpy (&dest[off], &rec, sizeof (rec)); + off += sizeof (rec); + if (off + rd[i].data_size > dest_size) + return -1; + memcpy (&dest[off], rd[i].data, rd[i].data_size); + off += rd[i].data_size; + } + return off; +} + + +/** + * Deserialize the given records to the given destination. + * + * @param len size of the serialized record data + * @param src the serialized record data + * @param rd_count number of records in the rd array + * @param dest where to put the data + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +int +GNUNET_NAMESTORE_records_deserialize (size_t len, + const char *src, + unsigned int rd_count, + struct GNUNET_NAMESTORE_RecordData *dest) +{ + struct NetworkRecord rec; + unsigned int i; + size_t off; + + off = 0; + for (i=0;i len) + return GNUNET_SYSERR; + memcpy (&rec, &src[off], sizeof (rec)); + dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time); + dest[i].data_size = ntohl ((uint32_t) rec.data_size); + dest[i].record_type = ntohl (rec.record_type); + dest[i].flags = ntohl (rec.flags); + off += sizeof (rec); + if (off + dest[i].data_size > len) + return GNUNET_SYSERR; + dest[i].data = &src[off]; + off += dest[i].data_size; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Deserialized record %u with flags %d and expiration time %llu\n", + i, + dest[i].flags, + (unsigned long long) dest[i].expiration_time); + } + return GNUNET_OK; +} + + +/* end of gnsrecord_serialization.c */ diff --git a/src/gnsrecord/test_gnsrecord_crypto.c b/src/gnsrecord/test_gnsrecord_crypto.c new file mode 100644 index 000000000..345bf353b --- /dev/null +++ b/src/gnsrecord/test_gnsrecord_crypto.c @@ -0,0 +1,145 @@ +/* + This file is part of GNUnet. + (C) 2013 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file gnsrecord/test_gnsrecord_crypto.c + * @brief testcase for block creation, verification and decryption + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_gnsrecord_lib.h" + +#define RECORDS 5 + +#define TEST_RECORD_TYPE 1234 + +#define TEST_RECORD_DATALEN 123 + +#define TEST_RECORD_DATA 'a' + +#define TEST_REMOVE_RECORD_TYPE 4321 + +#define TEST_REMOVE_RECORD_DATALEN 255 + +#define TEST_REMOVE_RECORD_DATA 'b' + + +static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey; + +static struct GNUNET_NAMESTORE_RecordData *s_rd; + +static char *s_name; + +static int res; + + +static struct GNUNET_NAMESTORE_RecordData * +create_record (int count) +{ + unsigned int c; + struct GNUNET_NAMESTORE_RecordData * rd; + + rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + for (c = 0; c < count; c++) + { + rd[c].expiration_time = GNUNET_TIME_absolute_get().abs_value_us; + rd[c].record_type = TEST_RECORD_TYPE; + rd[c].data_size = TEST_RECORD_DATALEN; + rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN); + memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); + } + return rd; +} + + +static void +rd_decrypt_cb (void *cls, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + char rd_cmp_data[TEST_RECORD_DATALEN]; + + int c; + + GNUNET_assert (RECORDS == rd_count); + GNUNET_assert (NULL != rd); + + memset (rd_cmp_data, 'a', TEST_RECORD_DATALEN); + + for (c = 0; c < rd_count; c++) + { + GNUNET_assert (TEST_RECORD_TYPE == rd[c].record_type); + GNUNET_assert (TEST_RECORD_DATALEN == rd[c].data_size); + GNUNET_assert (0 == memcmp (&rd_cmp_data, rd[c].data, TEST_RECORD_DATALEN)); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Block was decrypted successfully \n"); + res = 0; + +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct GNUNET_NAMESTORE_Block *block; + struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; + + /* load privat key */ + char *hostkey_file; + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + GNUNET_assert (privkey != NULL); + struct GNUNET_TIME_Absolute expire = GNUNET_TIME_absolute_get(); + /* get public key */ + GNUNET_CRYPTO_ecdsa_key_get_public(privkey, &pubkey); + + /* create record */ + s_name = "DUMMY.dummy.gnunet"; + s_rd = create_record (RECORDS); + + /* Create block */ + GNUNET_assert (NULL != (block = GNUNET_NAMESTORE_block_create (privkey, expire,s_name, s_rd, RECORDS))); + GNUNET_assert (GNUNET_OK == GNUNET_NAMESTORE_block_verify (block)); + GNUNET_assert (GNUNET_OK == GNUNET_NAMESTORE_block_decrypt (block, &pubkey, s_name, &rd_decrypt_cb, s_name)); + + GNUNET_free (block); +} + + +int +main (int argc, char *argv[]) +{ + static char *const argvx[] = { "test-gnsrecord-crypto", + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, argvx, "test-namestore-api", + "nohelp", options, &run, &res); + return res; +} + +/* end of test_gnsrecord_crypto.c */ diff --git a/src/gnsrecord/test_gnsrecord_serialization.c b/src/gnsrecord/test_gnsrecord_serialization.c new file mode 100644 index 000000000..de6a7ba1d --- /dev/null +++ b/src/gnsrecord/test_gnsrecord_serialization.c @@ -0,0 +1,140 @@ +/* + This file is part of GNUnet. + (C) 2013 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file gnsrecord/test_gnsrecord_serialization.c + * @brief testcase for gnsrecord_serialization.c + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_gnsrecord_lib.h" + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) + +static int res; + + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + size_t len; + int c; + + int rd_count = 3; + size_t data_len; + struct GNUNET_NAMESTORE_RecordData src[rd_count]; + + memset(src, '\0', rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + + data_len = 0; + for (c = 0; c < rd_count; c++) + { + src[c].record_type = c+1; + src[c].data_size = data_len; + src[c].data = GNUNET_malloc (data_len); + + /* Setting data to data_len * record_type */ + memset ((char *) src[c].data, 'a', data_len); + data_len += 10; + } + res = 0; + + len = GNUNET_NAMESTORE_records_get_size(rd_count, src); + char rd_ser[len]; + GNUNET_assert (len == GNUNET_NAMESTORE_records_serialize(rd_count, src, len, rd_ser)); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Serialized data len: %u\n",len); + + GNUNET_assert (rd_ser != NULL); + + struct GNUNET_NAMESTORE_RecordData dst[rd_count]; + GNUNET_assert (GNUNET_OK == GNUNET_NAMESTORE_records_deserialize (len, rd_ser, rd_count, dst)); + + GNUNET_assert (dst != NULL); + + for (c = 0; c < rd_count; c++) + { + if (src[c].data_size != dst[c].data_size) + { + GNUNET_break (0); + res = 1; + } + if (src[c].expiration_time != dst[c].expiration_time) + { + GNUNET_break (0); + res = 1; + } + if (src[c].flags != dst[c].flags) + { + GNUNET_break (0); + res = 1; + } + if (src[c].record_type != dst[c].record_type) + { + GNUNET_break (0); + res = 1; + } + + size_t data_size = src[c].data_size; + char data[data_size]; + memset (data, 'a', data_size); + if (0 != memcmp (data, dst[c].data, data_size)) + { + GNUNET_break (0); + res = 1; + } + if (0 != memcmp (data, src[c].data, data_size)) + { + GNUNET_break (0); + res = 1; + } + if (0 != memcmp (src[c].data, dst[c].data, src[c].data_size)) + { + GNUNET_break (0); + res = 1; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Element [%i]: EQUAL\n", c); + } + + for (c = 0; c < rd_count; c++) + { + GNUNET_free ((void *)src[c].data); + } +} + + +int +main (int argcx, char *argvx[]) +{ + static char *const argv[] = { "test_gnsrecord_serialization", + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test_namestore_record_serialization", + "nohelp", options, &run, &res); + return res; +} + +/* end of test_gnsrecord_serialization.c */ diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h index 2c8d73415..aefdeb4a4 100644 --- a/src/include/gnunet_gnsrecord_lib.h +++ b/src/include/gnunet_gnsrecord_lib.h @@ -34,6 +34,11 @@ extern "C" #endif #endif +/** + * Maximum size of a value that can be stored in a GNS block. + */ +#define GNUNET_NAMESTORE_MAX_VALUE_SIZE (63 * 1024) + /** * Record type indicating any record/'*' @@ -76,6 +81,144 @@ extern "C" #define GNUNET_GNSRECORD_TYPE_PHONE 65542 +/** + * Flags that can be set for a record. + */ +enum GNUNET_NAMESTORE_RecordFlags +{ + + /** + * No special options. + */ + GNUNET_NAMESTORE_RF_NONE = 0, + + /** + * This is a private record of this peer and it should + * thus not be handed out to other peers. + */ + GNUNET_NAMESTORE_RF_PRIVATE = 2, + + /** + * This record was added automatically by the system + * and is pending user confimation. + */ + GNUNET_NAMESTORE_RF_PENDING = 4, + + /** + * This expiration time of the record is a relative + * time (not an absolute time). + */ + GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION = 8, + + /** + * This record should not be used unless all (other) records with an absolute + * expiration time have expired. + */ + GNUNET_NAMESTORE_RF_SHADOW_RECORD = 16 + + /** + * When comparing flags for record equality for removal, + * which flags should must match (in addition to the type, + * name, expiration value and data of the record)? All flags + * that are not listed here will be ignored for this purpose. + * (for example, we don't expect that users will remember to + * pass the '--private' option when removing a record from + * the namestore, hence we don't require this particular option + * to match upon removal). See also + * #GNUNET_NAMESTORE_records_cmp. + */ +#define GNUNET_NAMESTORE_RF_RCMP_FLAGS (GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) +}; + + +/** + * A GNS record. + */ +struct GNUNET_NAMESTORE_RecordData +{ + + /** + * Binary value stored in the DNS record. Note: "data" must never + * be individually 'malloc'ed, but instead always points into some + * existing data area. + */ + const void *data; + + /** + * Expiration time for the DNS record. Can be relative + * or absolute, depending on 'flags'. Measured in the same + * unit as GNUnet time (microseconds). + */ + uint64_t expiration_time; + + /** + * Number of bytes in 'data'. + */ + size_t data_size; + + /** + * Type of the GNS/DNS record. + */ + uint32_t record_type; + + /** + * Flags for the record. + */ + enum GNUNET_NAMESTORE_RecordFlags flags; +}; + + + +GNUNET_NETWORK_STRUCT_BEGIN + + +/** + * Information we have in an encrypted block with record data (i.e. in the DHT). + */ +struct GNUNET_NAMESTORE_Block +{ + + /** + * Signature of the block. + */ + struct GNUNET_CRYPTO_EcdsaSignature signature; + + /** + * Derived key used for signing; hash of this is the query. + */ + struct GNUNET_CRYPTO_EcdsaPublicKey derived_key; + + /** + * Number of bytes signed; also specifies the number of bytes + * of encrypted data that follow. + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * Expiration time of the block. + */ + struct GNUNET_TIME_AbsoluteNBO expiration_time; + + /* followed by encrypted data */ +}; + +GNUNET_NETWORK_STRUCT_END + + +/** + * Process a records that were decrypted from a block. + * + * @param cls closure + * @param rd_count number of entries in @a rd array + * @param rd array of records with data to store + */ +typedef void (*GNUNET_NAMESTORE_RecordCallback) (void *cls, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd); + + + +/* ***************** API related to GNSRECORD plugins ************** */ /** * Convert the binary value @a data of a record of @@ -129,6 +272,217 @@ const char * GNUNET_GNSRECORD_number_to_typename (uint32_t type); +/* convenience APIs for serializing / deserializing GNS records */ + +/** + * Calculate how many bytes we will need to serialize the given + * records. + * + * @param rd_count number of records in the @a rd array + * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements + * @return the required size to serialize + */ +size_t +GNUNET_NAMESTORE_records_get_size (unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd); + + +/** + * Serialize the given records to the given destination buffer. + * + * @param rd_count number of records in the @a rd array + * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements + * @param dest_size size of the destination array @a dst + * @param dest where to write the result + * @return the size of serialized records, -1 if records do not fit + */ +ssize_t +GNUNET_NAMESTORE_records_serialize (unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + size_t dest_size, + char *dest); + + +/** + * Deserialize the given records to the given destination. + * + * @param len size of the serialized record data + * @param src the serialized record data + * @param rd_count number of records in the @a dest array + * @param dest where to put the data + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +int +GNUNET_NAMESTORE_records_deserialize (size_t len, + const char *src, + unsigned int rd_count, + struct GNUNET_NAMESTORE_RecordData *dest); + + +/* ******* general APIs relating to blocks, records and labels ******** */ + + + +/** + * Test if a given record is expired. + * + * @param rd record to test + * @return #GNUNET_YES if the record is expired, + * #GNUNET_NO if not + */ +int +GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd); + + +/** + * Convert a UTF-8 string to UTF-8 lowercase + * @param src source string + * @return converted result + */ +char * +GNUNET_NAMESTORE_normalize_string (const char *src); + + +/** + * Convert a zone to a string (for printing debug messages). + * This is one of the very few calls in the entire API that is + * NOT reentrant! + * + * @param z public key of a zone + * @return string form; will be overwritten by next call to #GNUNET_NAMESTORE_z2s. + */ +const char * +GNUNET_NAMESTORE_z2s (const struct GNUNET_CRYPTO_EcdsaPublicKey *z); + + +/** + * Convert public key to the respective absolute domain name in the + * ".zkey" pTLD. + * This is one of the very few calls in the entire API that is + * NOT reentrant! + * + * @param pkey a public key with a point on the eliptic curve + * @return string "X.zkey" where X is the coordinates of the public + * key in an encoding suitable for DNS labels. + */ +const char * +GNUNET_NAMESTORE_pkey_to_zkey (const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey); + + +/** + * Convert an absolute domain name in the ".zkey" pTLD to the + * respective public key. + * + * @param zkey string "X.zkey" where X is the public + * key in an encoding suitable for DNS labels. + * @param pkey set to a public key on the eliptic curve + * @return #GNUNET_SYSERR if @a zkey has the wrong syntax + */ +int +GNUNET_NAMESTORE_zkey_to_pkey (const char *zkey, + struct GNUNET_CRYPTO_EcdsaPublicKey *pkey); + + +/** + * Calculate the DHT query for a given @a label in a given @a zone. + * + * @param zone private key of the zone + * @param label label of the record + * @param query hash to use for the query + */ +void +GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *label, + struct GNUNET_HashCode *query); + + +/** + * Calculate the DHT query for a given @a label in a given @a zone. + * + * @param pub public key of the zone + * @param label label of the record + * @param query hash to use for the query + */ +void +GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, + const char *label, + struct GNUNET_HashCode *query); + + +/** + * Sign name and records + * + * @param key the private key + * @param expire block expiration + * @param label the name for the records + * @param rd record data + * @param rd_count number of records in @a rd + */ +struct GNUNET_NAMESTORE_Block * +GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, + struct GNUNET_TIME_Absolute expire, + const char *label, + const struct GNUNET_NAMESTORE_RecordData *rd, + unsigned int rd_count); + + +/** + * Check if a signature is valid. This API is used by the GNS Block + * to validate signatures received from the network. + * + * @param block block to verify + * @return #GNUNET_OK if the signature is valid + */ +int +GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block); + + +/** + * Decrypt block. + * + * @param block block to decrypt + * @param zone_key public key of the zone + * @param label the name for the records + * @param proc function to call with the result + * @param proc_cls closure for @a proc + * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was + * not well-formed + */ +int +GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block, + const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key, + const char *label, + GNUNET_NAMESTORE_RecordCallback proc, + void *proc_cls); + + +/** + * Compares if two records are equal + * + * @param a a record + * @param b another record + * @return #GNUNET_YES if the records are equal, or #GNUNET_NO if not. + */ +int +GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a, + const struct GNUNET_NAMESTORE_RecordData *b); + + +/** + * Returns the expiration time of the given block of records. The block + * expiration time is the expiration time of the record with smallest + * expiration time. + * + * @param rd_count number of records given in @a rd + * @param rd array of records + * @return absolute expiration time + */ +struct GNUNET_TIME_Absolute +GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd); + + + #if 0 /* keep Emacsens' auto-indent happy */ { #endif diff --git a/src/include/gnunet_namestore_service.h b/src/include/gnunet_namestore_service.h index 55fdbef65..30098832c 100644 --- a/src/include/gnunet_namestore_service.h +++ b/src/include/gnunet_namestore_service.h @@ -31,6 +31,7 @@ #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" +#include "gnunet_gnsrecord_lib.h" #ifdef __cplusplus extern "C" @@ -56,11 +57,6 @@ struct GNUNET_NAMESTORE_Handle; */ struct GNUNET_NAMESTORE_ZoneIterator; -/** - * Maximum size of a value that can be stored in the namestore. - */ -#define GNUNET_NAMESTORE_MAX_VALUE_SIZE (63 * 1024) - /** * Connect to the namestore service. @@ -98,131 +94,6 @@ typedef void (*GNUNET_NAMESTORE_ContinuationWithStatus) (void *cls, const char *emsg); -/** - * Flags that can be set for a record. - */ -enum GNUNET_NAMESTORE_RecordFlags -{ - - /** - * No special options. - */ - GNUNET_NAMESTORE_RF_NONE = 0, - - /** - * This is a private record of this peer and it should - * thus not be handed out to other peers. - */ - GNUNET_NAMESTORE_RF_PRIVATE = 2, - - /** - * This record was added automatically by the system - * and is pending user confimation. - */ - GNUNET_NAMESTORE_RF_PENDING = 4, - - /** - * This expiration time of the record is a relative - * time (not an absolute time). - */ - GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION = 8, - - /** - * This record should not be used unless all (other) records with an absolute - * expiration time have expired. - */ - GNUNET_NAMESTORE_RF_SHADOW_RECORD = 16 - - /** - * When comparing flags for record equality for removal, - * which flags should must match (in addition to the type, - * name, expiration value and data of the record)? All flags - * that are not listed here will be ignored for this purpose. - * (for example, we don't expect that users will remember to - * pass the '--private' option when removing a record from - * the namestore, hence we don't require this particular option - * to match upon removal). See also - * #GNUNET_NAMESTORE_records_cmp. - */ -#define GNUNET_NAMESTORE_RF_RCMP_FLAGS (GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) -}; - - -/** - * A GNS record. - */ -struct GNUNET_NAMESTORE_RecordData -{ - - /** - * Binary value stored in the DNS record. Note: "data" must never - * be individually 'malloc'ed, but instead always points into some - * existing data area. - */ - const void *data; - - /** - * Expiration time for the DNS record. Can be relative - * or absolute, depending on 'flags'. Measured in the same - * unit as GNUnet time (microseconds). - */ - uint64_t expiration_time; - - /** - * Number of bytes in 'data'. - */ - size_t data_size; - - /** - * Type of the GNS/DNS record. - */ - uint32_t record_type; - - /** - * Flags for the record. - */ - enum GNUNET_NAMESTORE_RecordFlags flags; -}; - - - -GNUNET_NETWORK_STRUCT_BEGIN - - -/** - * Information we have in an encrypted block with record data (i.e. in the DHT). - */ -struct GNUNET_NAMESTORE_Block -{ - - /** - * Signature of the block. - */ - struct GNUNET_CRYPTO_EcdsaSignature signature; - - /** - * Derived key used for signing; hash of this is the query. - */ - struct GNUNET_CRYPTO_EcdsaPublicKey derived_key; - - /** - * Number of bytes signed; also specifies the number of bytes - * of encrypted data that follow. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Expiration time of the block. - */ - struct GNUNET_TIME_AbsoluteNBO expiration_time; - - /* followed by encrypted data */ -}; - - - -GNUNET_NETWORK_STRUCT_END - /** * Store an item in the namestore. If the item is already present, * it is replaced with the new record. @@ -328,18 +199,6 @@ GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h, GNUNET_NAMESTORE_RecordMonitor proc, void *proc_cls); -/** - * Process a records that were decrypted from a block. - * - * @param cls closure - * @param rd_count number of entries in @a rd array - * @param rd array of records with data to store - */ -typedef void (*GNUNET_NAMESTORE_RecordCallback) (void *cls, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd); - - /** * Cancel a namestore operation. The final callback from the * operation must not have been done yet. Must be called on any @@ -445,211 +304,6 @@ void GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm); -/* convenience APIs for serializing / deserializing GNS records */ - -/** - * Calculate how many bytes we will need to serialize the given - * records. - * - * @param rd_count number of records in the @a rd array - * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements - * @return the required size to serialize - */ -size_t -GNUNET_NAMESTORE_records_get_size (unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd); - - -/** - * Serialize the given records to the given destination buffer. - * - * @param rd_count number of records in the @a rd array - * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements - * @param dest_size size of the destination array @a dst - * @param dest where to write the result - * @return the size of serialized records, -1 if records do not fit - */ -ssize_t -GNUNET_NAMESTORE_records_serialize (unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd, - size_t dest_size, - char *dest); - - -/** - * Deserialize the given records to the given destination. - * - * @param len size of the serialized record data - * @param src the serialized record data - * @param rd_count number of records in the @a dest array - * @param dest where to put the data - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -int -GNUNET_NAMESTORE_records_deserialize (size_t len, - const char *src, - unsigned int rd_count, - struct GNUNET_NAMESTORE_RecordData *dest); - - -/** - * Test if a given record is expired. - * - * @param rd record to test - * @return #GNUNET_YES if the record is expired, - * #GNUNET_NO if not - */ -int -GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd); - - -/** - * Convert a UTF-8 string to UTF-8 lowercase - * @param src source string - * @return converted result - */ -char * -GNUNET_NAMESTORE_normalize_string (const char *src); - - -/** - * Convert a zone to a string (for printing debug messages). - * This is one of the very few calls in the entire API that is - * NOT reentrant! - * - * @param z public key of a zone - * @return string form; will be overwritten by next call to #GNUNET_NAMESTORE_z2s. - */ -const char * -GNUNET_NAMESTORE_z2s (const struct GNUNET_CRYPTO_EcdsaPublicKey *z); - - -/** - * Convert public key to the respective absolute domain name in the - * ".zkey" pTLD. - * This is one of the very few calls in the entire API that is - * NOT reentrant! - * - * @param pkey a public key with a point on the eliptic curve - * @return string "X.zkey" where X is the coordinates of the public - * key in an encoding suitable for DNS labels. - */ -const char * -GNUNET_NAMESTORE_pkey_to_zkey (const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey); - - -/** - * Convert an absolute domain name in the ".zkey" pTLD to the - * respective public key. - * - * @param zkey string "X.zkey" where X is the public - * key in an encoding suitable for DNS labels. - * @param pkey set to a public key on the eliptic curve - * @return #GNUNET_SYSERR if @a zkey has the wrong syntax - */ -int -GNUNET_NAMESTORE_zkey_to_pkey (const char *zkey, - struct GNUNET_CRYPTO_EcdsaPublicKey *pkey); - - -/** - * Calculate the DHT query for a given @a label in a given @a zone. - * - * @param zone private key of the zone - * @param label label of the record - * @param query hash to use for the query - */ -void -GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, - const char *label, - struct GNUNET_HashCode *query); - - -/** - * Calculate the DHT query for a given @a label in a given @a zone. - * - * @param pub public key of the zone - * @param label label of the record - * @param query hash to use for the query - */ -void -GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, - const char *label, - struct GNUNET_HashCode *query); - - -/** - * Sign name and records - * - * @param key the private key - * @param expire block expiration - * @param label the name for the records - * @param rd record data - * @param rd_count number of records in @a rd - */ -struct GNUNET_NAMESTORE_Block * -GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, - struct GNUNET_TIME_Absolute expire, - const char *label, - const struct GNUNET_NAMESTORE_RecordData *rd, - unsigned int rd_count); - - -/** - * Check if a signature is valid. This API is used by the GNS Block - * to validate signatures received from the network. - * - * @param block block to verify - * @return #GNUNET_OK if the signature is valid - */ -int -GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block); - - -/** - * Decrypt block. - * - * @param block block to decrypt - * @param zone_key public key of the zone - * @param label the name for the records - * @param proc function to call with the result - * @param proc_cls closure for @a proc - * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was - * not well-formed - */ -int -GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block, - const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key, - const char *label, - GNUNET_NAMESTORE_RecordCallback proc, - void *proc_cls); - - -/** - * Compares if two records are equal - * - * @param a a record - * @param b another record - * @return #GNUNET_YES if the records are equal, or #GNUNET_NO if not. - */ -int -GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a, - const struct GNUNET_NAMESTORE_RecordData *b); - - -/** - * Returns the expiration time of the given block of records. The block - * expiration time is the expiration time of the record with smallest - * expiration time. - * - * @param rd_count number of records given in @a rd - * @param rd array of records - * @return absolute expiration time - */ -struct GNUNET_TIME_Absolute -GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd); - #if 0 /* keep Emacsens' auto-indent happy */ { diff --git a/src/namecache/Makefile.am b/src/namecache/Makefile.am index b8ad9b7fa..162177603 100644 --- a/src/namecache/Makefile.am +++ b/src/namecache/Makefile.am @@ -75,7 +75,6 @@ bin_PROGRAMS = \ gnunet_namecache_SOURCES = \ gnunet-namecache.c gnunet_namecache_LDADD = \ - $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamecache.la \ @@ -90,7 +89,7 @@ gnunet_service_namecache_SOURCES = \ gnunet-service-namecache.c gnunet_service_namecache_LDADD = \ - $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamecache.la \ @@ -139,7 +138,7 @@ libgnunet_plugin_namecache_postgres_la_DEPENDENCIES = \ test_namecache_api_cache_block_SOURCES = \ test_namecache_api_cache_block.c test_namecache_api_cache_block_LDADD = \ - $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am index 1c9b297ae..11e23a790 100644 --- a/src/namestore/Makefile.am +++ b/src/namestore/Makefile.am @@ -53,8 +53,6 @@ endif if HAVE_SQLITE check_PROGRAMS = \ - test_namestore_record_serialization \ - test_namestore_api_blocks \ $(SQLITE_TESTS) \ $(POSTGRES_TESTS) \ $(TESTING_TESTS) @@ -72,7 +70,6 @@ lib_LTLIBRARIES = \ libgnunetnamestore_la_SOURCES = \ namestore_api.c \ namestore_api_monitor.c \ - namestore_api_common.c \ namestore.h libgnunetnamestore_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ @@ -126,6 +123,7 @@ gnunet_service_namestore_SOURCES = \ gnunet-service-namestore.c gnunet_service_namestore_LDADD = \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la \ @@ -171,18 +169,12 @@ libgnunet_plugin_namestore_postgres_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la -test_namestore_api_blocks_SOURCES = \ - test_namestore_api_blocks.c -test_namestore_api_blocks_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la - test_namestore_api_store_SOURCES = \ test_namestore_api_store.c test_namestore_api_store_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_store_update_SOURCES = \ @@ -190,6 +182,7 @@ test_namestore_api_store_update_SOURCES = \ test_namestore_api_store_update_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_cache_block_SOURCES = \ @@ -197,6 +190,7 @@ test_namestore_api_cache_block_SOURCES = \ test_namestore_api_cache_block_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_lookup_public_SOURCES = \ @@ -204,6 +198,7 @@ test_namestore_api_lookup_public_SOURCES = \ test_namestore_api_lookup_public_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_put_SOURCES = \ @@ -211,6 +206,7 @@ test_namestore_api_put_SOURCES = \ test_namestore_api_put_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_remove_SOURCES = \ @@ -218,6 +214,7 @@ test_namestore_api_remove_SOURCES = \ test_namestore_api_remove_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_remove_not_existing_record_SOURCES = \ @@ -225,6 +222,7 @@ test_namestore_api_remove_not_existing_record_SOURCES = \ test_namestore_api_remove_not_existing_record_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_zone_to_name_SOURCES = \ @@ -239,6 +237,7 @@ test_namestore_api_monitoring_SOURCES = \ test_namestore_api_monitoring_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la test_namestore_api_monitoring_existing_SOURCES = \ @@ -246,6 +245,7 @@ test_namestore_api_monitoring_existing_SOURCES = \ test_namestore_api_monitoring_existing_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la test_namestore_api_zone_iteration_SOURCES = \ @@ -253,6 +253,7 @@ test_namestore_api_zone_iteration_SOURCES = \ test_namestore_api_zone_iteration_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_zone_iteration_specific_zone_SOURCES = \ @@ -260,6 +261,7 @@ test_namestore_api_zone_iteration_specific_zone_SOURCES = \ test_namestore_api_zone_iteration_specific_zone_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_zone_iteration_stop_SOURCES = \ @@ -267,13 +269,7 @@ test_namestore_api_zone_iteration_stop_SOURCES = \ test_namestore_api_zone_iteration_stop_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la - -test_namestore_record_serialization_SOURCES = \ - test_namestore_record_serialization.c -test_namestore_record_serialization_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_plugin_namestore_sqlite_SOURCES = \ diff --git a/src/namestore/namestore_api_common.c b/src/namestore/namestore_api_common.c deleted file mode 100644 index 388722cd3..000000000 --- a/src/namestore/namestore_api_common.c +++ /dev/null @@ -1,638 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009-2013 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file namestore/namestore_api_common.c - * @brief API to access the NAMESTORE service - * @author Martin Schanzenbach - * @author Matthias Wachs - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_constants.h" -#include "gnunet_signatures.h" -#include "gnunet_arm_service.h" -#include "gnunet_conversation_service.h" -#include "gnunet_namestore_service.h" -#include "gnunet_dnsparser_lib.h" -#include "gnunet_tun_lib.h" -#include "namestore.h" - - -#define LOG(kind,...) GNUNET_log_from (kind, "namestore-api",__VA_ARGS__) - -GNUNET_NETWORK_STRUCT_BEGIN - - -/** - * Internal format of a record in the serialized form. - */ -struct NetworkRecord -{ - - /** - * Expiration time for the DNS record; relative or absolute depends - * on 'flags', network byte order. - */ - uint64_t expiration_time GNUNET_PACKED; - - /** - * Number of bytes in 'data', network byte order. - */ - uint32_t data_size GNUNET_PACKED; - - /** - * Type of the GNS/DNS record, network byte order. - */ - uint32_t record_type GNUNET_PACKED; - - /** - * Flags for the record, network byte order. - */ - uint32_t flags GNUNET_PACKED; - -}; - -GNUNET_NETWORK_STRUCT_END - -/** - * Convert a UTF-8 string to UTF-8 lowercase - * @param src source string - * @return converted result - */ -char * -GNUNET_NAMESTORE_normalize_string (const char *src) -{ - GNUNET_assert (NULL != src); - char *res = strdup (src); - /* normalize */ - GNUNET_STRINGS_utf8_tolower(src, &res); - return res; -} - - -/** - * Convert a zone key to a string (for printing debug messages). - * This is one of the very few calls in the entire API that is - * NOT reentrant! - * - * @param z the zone key - * @return string form; will be overwritten by next call to #GNUNET_NAMESTORE_z2s - */ -const char * -GNUNET_NAMESTORE_z2s (const struct GNUNET_CRYPTO_EcdsaPublicKey *z) -{ - static char buf[sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) * 8]; - char *end; - - end = GNUNET_STRINGS_data_to_string ((const unsigned char *) z, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), - buf, sizeof (buf)); - if (NULL == end) - { - GNUNET_break (0); - return NULL; - } - *end = '\0'; - return buf; -} - - -/** - * Calculate how many bytes we will need to serialize the given - * records. - * - * @param rd_count number of records in the rd array - * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements - * @return the required size to serialize - */ -size_t -GNUNET_NAMESTORE_records_get_size (unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) -{ - unsigned int i; - size_t ret; - - ret = sizeof (struct NetworkRecord) * rd_count; - for (i=0;i= ret); - ret += rd[i].data_size; - } - return ret; -} - - -/** - * Serialize the given records to the given destination buffer. - * - * @param rd_count number of records in the rd array - * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements - * @param dest_size size of the destination array - * @param dest where to write the result - * @return the size of serialized records, -1 if records do not fit - */ -ssize_t -GNUNET_NAMESTORE_records_serialize (unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd, - size_t dest_size, - char *dest) -{ - struct NetworkRecord rec; - unsigned int i; - size_t off; - - off = 0; - for (i=0;i dest_size) - return -1; - memcpy (&dest[off], &rec, sizeof (rec)); - off += sizeof (rec); - if (off + rd[i].data_size > dest_size) - return -1; - memcpy (&dest[off], rd[i].data, rd[i].data_size); - off += rd[i].data_size; - } - return off; -} - - -/** - * Compares if two records are equal (ignoring flags such - * as authority, private and pending, but not relative vs. - * absolute expiration time). - * - * @param a record - * @param b record - * @return #GNUNET_YES if the records are equal or #GNUNET_NO if they are not - */ -int -GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a, - const struct GNUNET_NAMESTORE_RecordData *b) -{ - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Comparing records\n"); - if (a->record_type != b->record_type) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Record type %lu != %lu\n", a->record_type, b->record_type); - return GNUNET_NO; - } - if ((a->expiration_time != b->expiration_time) && - ((a->expiration_time != 0) && (b->expiration_time != 0))) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Expiration time %llu != %llu\n", - a->expiration_time, - b->expiration_time); - return GNUNET_NO; - } - if ((a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS) - != (b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Flags %lu (%lu) != %lu (%lu)\n", a->flags, - a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS, b->flags, - b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS); - return GNUNET_NO; - } - if (a->data_size != b->data_size) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Data size %lu != %lu\n", - a->data_size, - b->data_size); - return GNUNET_NO; - } - if (0 != memcmp (a->data, b->data, a->data_size)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Data contents do not match\n"); - return GNUNET_NO; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Records are equal\n"); - return GNUNET_YES; -} - - -/** - * Deserialize the given records to the given destination. - * - * @param len size of the serialized record data - * @param src the serialized record data - * @param rd_count number of records in the rd array - * @param dest where to put the data - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -int -GNUNET_NAMESTORE_records_deserialize (size_t len, - const char *src, - unsigned int rd_count, - struct GNUNET_NAMESTORE_RecordData *dest) -{ - struct NetworkRecord rec; - unsigned int i; - size_t off; - - off = 0; - for (i=0;i len) - return GNUNET_SYSERR; - memcpy (&rec, &src[off], sizeof (rec)); - dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time); - dest[i].data_size = ntohl ((uint32_t) rec.data_size); - dest[i].record_type = ntohl (rec.record_type); - dest[i].flags = ntohl (rec.flags); - off += sizeof (rec); - if (off + dest[i].data_size > len) - return GNUNET_SYSERR; - dest[i].data = &src[off]; - off += dest[i].data_size; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Deserialized record %u with flags %d and expiration time %llu\n", - i, - dest[i].flags, - (unsigned long long) dest[i].expiration_time); - } - return GNUNET_OK; -} - - -/** - * Returns the expiration time of the given block of records. The block - * expiration time is the expiration time of the record with smallest - * expiration time. - * - * @param rd_count number of records given in @a rd - * @param rd array of records - * @return absolute expiration time - */ -struct GNUNET_TIME_Absolute -GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) -{ - unsigned int c; - struct GNUNET_TIME_Absolute expire; - struct GNUNET_TIME_Absolute at; - struct GNUNET_TIME_Relative rt; - - if (NULL == rd) - return GNUNET_TIME_UNIT_ZERO_ABS; - expire = GNUNET_TIME_UNIT_FOREVER_ABS; - for (c = 0; c < rd_count; c++) - { - if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) - { - rt.rel_value_us = rd[c].expiration_time; - at = GNUNET_TIME_relative_to_absolute (rt); - } - else - { - at.abs_value_us = rd[c].expiration_time; - } - expire = GNUNET_TIME_absolute_min (at, expire); - } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Determined expiration time for block with %u records to be %s\n", - rd_count, - GNUNET_STRINGS_absolute_time_to_string (expire)); - return expire; -} - - -/** - * Derive session key and iv from label and public key. - * - * @param iv initialization vector to initialize - * @param skey session key to initialize - * @param label label to use for KDF - * @param pub public key to use for KDF - */ -static void -derive_block_aes_key (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, - struct GNUNET_CRYPTO_SymmetricSessionKey *skey, - const char *label, - const struct GNUNET_CRYPTO_EcdsaPublicKey *pub) -{ - static const char ctx_key[] = "gns-aes-ctx-key"; - static const char ctx_iv[] = "gns-aes-ctx-iv"; - - GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), - pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), - label, strlen (label), - ctx_key, strlen (ctx_key), - NULL, 0); - GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector), - pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), - label, strlen (label), - ctx_iv, strlen (ctx_iv), - NULL, 0); -} - - -/** - * Sign name and records - * - * @param key the private key - * @param expire block expiration - * @param label the name for the records - * @param rd record data - * @param rd_count number of records - * @return NULL on error (block too large) - */ -struct GNUNET_NAMESTORE_Block * -GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, - struct GNUNET_TIME_Absolute expire, - const char *label, - const struct GNUNET_NAMESTORE_RecordData *rd, - unsigned int rd_count) -{ - size_t payload_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd); - char payload[sizeof (uint32_t) + payload_len]; - struct GNUNET_NAMESTORE_Block *block; - struct GNUNET_CRYPTO_EcdsaPublicKey pkey; - struct GNUNET_CRYPTO_EcdsaPrivateKey *dkey; - struct GNUNET_CRYPTO_SymmetricInitializationVector iv; - struct GNUNET_CRYPTO_SymmetricSessionKey skey; - uint32_t rd_count_nbo; - - if (payload_len > GNUNET_NAMESTORE_MAX_VALUE_SIZE) - return NULL; - rd_count_nbo = htonl (rd_count); - memcpy (payload, &rd_count_nbo, sizeof (uint32_t)); - GNUNET_assert (payload_len == - GNUNET_NAMESTORE_records_serialize (rd_count, rd, - payload_len, &payload[sizeof (uint32_t)])); - block = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Block) + - sizeof (uint32_t) + payload_len); - block->purpose.size = htonl (sizeof (uint32_t) + payload_len + - sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + - sizeof (struct GNUNET_TIME_AbsoluteNBO)); - block->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); - block->expiration_time = GNUNET_TIME_absolute_hton (expire); - dkey = GNUNET_CRYPTO_ecdsa_private_key_derive (key, - label, - "gns"); - GNUNET_CRYPTO_ecdsa_key_get_public (dkey, - &block->derived_key); - GNUNET_CRYPTO_ecdsa_key_get_public (key, - &pkey); - derive_block_aes_key (&iv, &skey, label, &pkey); - GNUNET_break (payload_len + sizeof (uint32_t) == - GNUNET_CRYPTO_symmetric_encrypt (payload, payload_len + sizeof (uint32_t), - &skey, &iv, - &block[1])); - if (GNUNET_OK != - GNUNET_CRYPTO_ecdsa_sign (dkey, - &block->purpose, - &block->signature)) - { - GNUNET_break (0); - GNUNET_free (dkey); - GNUNET_free (block); - return NULL; - } - GNUNET_free (dkey); - return block; -} - - -/** - * Check if a signature is valid. This API is used by the GNS Block - * to validate signatures received from the network. - * - * @param block block to verify - * @return #GNUNET_OK if the signature is valid - */ -int -GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block) -{ - return GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, - &block->purpose, - &block->signature, - &block->derived_key); -} - - -/** - * Decrypt block. - * - * @param block block to decrypt - * @param zone_key public key of the zone - * @param label the name for the records - * @param proc function to call with the result - * @param proc_cls closure for proc - * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was - * not well-formed - */ -int -GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block, - const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key, - const char *label, - GNUNET_NAMESTORE_RecordCallback proc, - void *proc_cls) -{ - size_t payload_len = ntohl (block->purpose.size) - - sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) - - sizeof (struct GNUNET_TIME_AbsoluteNBO); - struct GNUNET_CRYPTO_SymmetricInitializationVector iv; - struct GNUNET_CRYPTO_SymmetricSessionKey skey; - - if (ntohl (block->purpose.size) < - sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + - sizeof (struct GNUNET_TIME_AbsoluteNBO)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - derive_block_aes_key (&iv, &skey, label, zone_key); - { - char payload[payload_len]; - uint32_t rd_count; - - GNUNET_break (payload_len == - GNUNET_CRYPTO_symmetric_decrypt (&block[1], payload_len, - &skey, &iv, - payload)); - memcpy (&rd_count, - payload, - sizeof (uint32_t)); - rd_count = ntohl (rd_count); - if (rd_count > 2048) - { - /* limit to sane value */ - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - { - struct GNUNET_NAMESTORE_RecordData rd[rd_count]; - - if (GNUNET_OK != - GNUNET_NAMESTORE_records_deserialize (payload_len - sizeof (uint32_t), - &payload[sizeof (uint32_t)], - rd_count, - rd)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (NULL != proc) - proc (proc_cls, rd_count, (0 != rd_count) ? rd : NULL); - } - } - return GNUNET_OK; -} - - -/** - * Test if a given record is expired. - * - * @return #GNUNET_YES if the record is expired, - * #GNUNET_NO if not - */ -int -GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd) -{ - struct GNUNET_TIME_Absolute at; - - if (0 != (rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) - return GNUNET_NO; - at.abs_value_us = rd->expiration_time; - return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value_us) ? GNUNET_YES : GNUNET_NO; -} - - -/** - * Calculate the DHT query for a given @a label in a given @a zone. - * - * @param zone private key of the zone - * @param label label of the record - * @param query hash to use for the query - */ -void -GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, - const char *label, - struct GNUNET_HashCode *query) -{ - struct GNUNET_CRYPTO_EcdsaPublicKey pub; - - GNUNET_CRYPTO_ecdsa_key_get_public (zone, &pub); - GNUNET_NAMESTORE_query_from_public_key (&pub, label, query); -} - - -/** - * Calculate the DHT query for a given @a label in a given @a zone. - * - * @param pub public key of the zone - * @param label label of the record - * @param query hash to use for the query - */ -void -GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, - const char *label, - struct GNUNET_HashCode *query) -{ - struct GNUNET_CRYPTO_EcdsaPublicKey pd; - - GNUNET_CRYPTO_ecdsa_public_key_derive (pub, label, "gns", &pd); - GNUNET_CRYPTO_hash (&pd, sizeof (pd), query); -} - - -/** - * Convert public key to the respective absolute domain name in the - * ".zkey" pTLD. - * This is one of the very few calls in the entire API that is - * NOT reentrant! - * - * @param pkey a public key with a point on the eliptic curve - * @return string "X.zkey" where X is the public - * key in an encoding suitable for DNS labels. - */ -const char * -GNUNET_NAMESTORE_pkey_to_zkey (const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey) -{ - static char ret[128]; - char *pkeys; - - pkeys = GNUNET_CRYPTO_ecdsa_public_key_to_string (pkey); - GNUNET_snprintf (ret, - sizeof (ret), - "%s.zkey", - pkeys); - GNUNET_free (pkeys); - return ret; -} - - -/** - * Convert an absolute domain name in the ".zkey" pTLD to the - * respective public key. - * - * @param zkey string "X.zkey" where X is the coordinates of the public - * key in an encoding suitable for DNS labels. - * @param pkey set to a public key on the eliptic curve - * @return #GNUNET_SYSERR if @a zkey has the wrong syntax - */ -int -GNUNET_NAMESTORE_zkey_to_pkey (const char *zkey, - struct GNUNET_CRYPTO_EcdsaPublicKey *pkey) -{ - char *cpy; - char *dot; - const char *x; - - cpy = GNUNET_strdup (zkey); - x = cpy; - if (NULL == (dot = strchr (x, (int) '.'))) - goto error; - *dot = '\0'; - if (0 != strcasecmp (dot + 1, - "zkey")) - goto error; - - if (GNUNET_OK != - GNUNET_CRYPTO_ecdsa_public_key_from_string (x, - strlen (x), - pkey)) - goto error; - GNUNET_free (cpy); - return GNUNET_OK; - error: - GNUNET_free (cpy); - return GNUNET_SYSERR; -} - - -/* end of namestore_common.c */ diff --git a/src/namestore/test_namestore_api_blocks.c b/src/namestore/test_namestore_api_blocks.c deleted file mode 100644 index 001e7e182..000000000 --- a/src/namestore/test_namestore_api_blocks.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ -/** - * @file namestore/test_namestore_api_blocks.c - * @brief testcase for block creation, verification and decryption - */ -#include "platform.h" -#include "gnunet_namestore_service.h" -#include "namestore.h" - -#define RECORDS 5 - -#define TEST_RECORD_TYPE 1234 - -#define TEST_RECORD_DATALEN 123 - -#define TEST_RECORD_DATA 'a' - -#define TEST_REMOVE_RECORD_TYPE 4321 - -#define TEST_REMOVE_RECORD_DATALEN 255 - -#define TEST_REMOVE_RECORD_DATA 'b' - - -static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey; - -static struct GNUNET_NAMESTORE_RecordData *s_rd; - -static char *s_name; - -static int res; - - -static struct GNUNET_NAMESTORE_RecordData * -create_record (int count) -{ - unsigned int c; - struct GNUNET_NAMESTORE_RecordData * rd; - - rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); - for (c = 0; c < count; c++) - { - rd[c].expiration_time = GNUNET_TIME_absolute_get().abs_value_us; - rd[c].record_type = TEST_RECORD_TYPE; - rd[c].data_size = TEST_RECORD_DATALEN; - rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN); - memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); - } - return rd; -} - - -static void -rd_decrypt_cb (void *cls, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) -{ - char rd_cmp_data[TEST_RECORD_DATALEN]; - - int c; - - GNUNET_assert (RECORDS == rd_count); - GNUNET_assert (NULL != rd); - - memset (rd_cmp_data, 'a', TEST_RECORD_DATALEN); - - for (c = 0; c < rd_count; c++) - { - GNUNET_assert (TEST_RECORD_TYPE == rd[c].record_type); - GNUNET_assert (TEST_RECORD_DATALEN == rd[c].data_size); - GNUNET_assert (0 == memcmp (&rd_cmp_data, rd[c].data, TEST_RECORD_DATALEN)); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Block was decrypted successfully \n"); - res = 0; - -} - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_NAMESTORE_Block *block; - struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; - - /* load privat key */ - char *hostkey_file; - GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, - "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); - privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); - GNUNET_free (hostkey_file); - GNUNET_assert (privkey != NULL); - struct GNUNET_TIME_Absolute expire = GNUNET_TIME_absolute_get(); - /* get public key */ - GNUNET_CRYPTO_ecdsa_key_get_public(privkey, &pubkey); - - /* create record */ - s_name = "DUMMY.dummy.gnunet"; - s_rd = create_record (RECORDS); - - /* Create block */ - GNUNET_assert (NULL != (block = GNUNET_NAMESTORE_block_create (privkey, expire,s_name, s_rd, RECORDS))); - GNUNET_assert (GNUNET_OK == GNUNET_NAMESTORE_block_verify (block)); - GNUNET_assert (GNUNET_OK == GNUNET_NAMESTORE_block_decrypt (block, &pubkey, s_name, &rd_decrypt_cb, s_name)); - - GNUNET_free (block); -} - - -int -main (int argc, char *argv[]) -{ - static char *const argvx[] = { "test-namestore-api", - "-c", - "test_namestore_api.conf", - NULL - }; - static struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - res = 1; - GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, argvx, "test-namestore-api", - "nohelp", options, &run, &res); - return res; -} - -/* end of test_namestore_api_blocks.c */ diff --git a/src/namestore/test_namestore_record_serialization.c b/src/namestore/test_namestore_record_serialization.c deleted file mode 100644 index 288ecb841..000000000 --- a/src/namestore/test_namestore_record_serialization.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ -/** - * @file namestore/test_namestore_record_serialization.c - * @brief testcase for test_namestore_record_serialization.c - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_namestore_service.h" -#include "namestore.h" - -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) - -static int res; - - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - size_t len; - int c; - - int rd_count = 3; - size_t data_len; - struct GNUNET_NAMESTORE_RecordData src[rd_count]; - - memset(src, '\0', rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); - - data_len = 0; - for (c = 0; c < rd_count; c++) - { - src[c].record_type = c+1; - src[c].data_size = data_len; - src[c].data = GNUNET_malloc (data_len); - - /* Setting data to data_len * record_type */ - memset ((char *) src[c].data, 'a', data_len); - data_len += 10; - } - res = 0; - - len = GNUNET_NAMESTORE_records_get_size(rd_count, src); - char rd_ser[len]; - GNUNET_assert (len == GNUNET_NAMESTORE_records_serialize(rd_count, src, len, rd_ser)); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Serialized data len: %u\n",len); - - GNUNET_assert (rd_ser != NULL); - - struct GNUNET_NAMESTORE_RecordData dst[rd_count]; - GNUNET_assert (GNUNET_OK == GNUNET_NAMESTORE_records_deserialize (len, rd_ser, rd_count, dst)); - - GNUNET_assert (dst != NULL); - - for (c = 0; c < rd_count; c++) - { - if (src[c].data_size != dst[c].data_size) - { - GNUNET_break (0); - res = 1; - } - if (src[c].expiration_time != dst[c].expiration_time) - { - GNUNET_break (0); - res = 1; - } - if (src[c].flags != dst[c].flags) - { - GNUNET_break (0); - res = 1; - } - if (src[c].record_type != dst[c].record_type) - { - GNUNET_break (0); - res = 1; - } - - size_t data_size = src[c].data_size; - char data[data_size]; - memset (data, 'a', data_size); - if (0 != memcmp (data, dst[c].data, data_size)) - { - GNUNET_break (0); - res = 1; - } - if (0 != memcmp (data, src[c].data, data_size)) - { - GNUNET_break (0); - res = 1; - } - if (0 != memcmp (src[c].data, dst[c].data, src[c].data_size)) - { - GNUNET_break (0); - res = 1; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Element [%i]: EQUAL\n", c); - } - - for (c = 0; c < rd_count; c++) - { - GNUNET_free ((void *)src[c].data); - } -} - -static int -check () -{ - static char *const argv[] = { "test_namestore_record_serialization", - "-c", - "test_namestore_api.conf", - NULL - }; - static struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - res = 1; - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test_namestore_record_serialization", - "nohelp", options, &run, &res); - return res; -} - -int -main (int argc, char *argv[]) -{ - int ret; - - ret = check (); - - return ret; -} - -/* end of test_namestore_record_serialization.c */ -- cgit v1.2.3