aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-10-16 20:14:02 +0000
committerChristian Grothoff <christian@grothoff.org>2013-10-16 20:14:02 +0000
commit3d670727232e79b7e49a1df7ba9260db4e5798a0 (patch)
tree093f7b5aec28134dc6c5fe34cd2d8bfb1e1445ad
parent2de26776993a5e591e487321a5dc1d62b86d9cd4 (diff)
downloadgnunet-3d670727232e79b7e49a1df7ba9260db4e5798a0.tar.gz
gnunet-3d670727232e79b7e49a1df7ba9260db4e5798a0.zip
-moving namestore_common functions to gnsrecord library
-rw-r--r--src/conversation/Makefile.am1
-rw-r--r--src/gns/Makefile.am4
-rw-r--r--src/gnsrecord/Makefile.am23
-rw-r--r--src/gnsrecord/gnsrecord_crypto.c263
-rw-r--r--src/gnsrecord/gnsrecord_misc.c267
-rw-r--r--src/gnsrecord/gnsrecord_serialization.c188
-rw-r--r--src/gnsrecord/test_gnsrecord_crypto.c (renamed from src/namestore/test_namestore_api_blocks.c)14
-rw-r--r--src/gnsrecord/test_gnsrecord_serialization.c (renamed from src/namestore/test_namestore_record_serialization.c)30
-rw-r--r--src/include/gnunet_gnsrecord_lib.h354
-rw-r--r--src/include/gnunet_namestore_service.h348
-rw-r--r--src/namecache/Makefile.am5
-rw-r--r--src/namestore/Makefile.am30
-rw-r--r--src/namestore/namestore_api_common.c638
13 files changed, 1130 insertions, 1035 deletions
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 = \
52 conversation_api.c 52 conversation_api.c
53libgnunetconversation_la_LIBADD = \ 53libgnunetconversation_la_LIBADD = \
54 $(top_builddir)/src/gns/libgnunetgns.la \ 54 $(top_builddir)/src/gns/libgnunetgns.la \
55 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
55 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 56 $(top_builddir)/src/namestore/libgnunetnamestore.la \
56 $(top_builddir)/src/identity/libgnunetidentity.la \ 57 $(top_builddir)/src/identity/libgnunetidentity.la \
57 $(top_builddir)/src/util/libgnunetutil.la 58 $(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 = \
100gnunet_dns2gns_SOURCES = \ 100gnunet_dns2gns_SOURCES = \
101 gnunet-dns2gns.c 101 gnunet-dns2gns.c
102gnunet_dns2gns_LDADD = \ 102gnunet_dns2gns_LDADD = \
103 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
103 $(top_builddir)/src/gns/libgnunetgns.la \ 104 $(top_builddir)/src/gns/libgnunetgns.la \
104 $(top_builddir)/src/util/libgnunetutil.la \ 105 $(top_builddir)/src/util/libgnunetutil.la \
105 $(top_builddir)/src/identity/libgnunetidentity.la \ 106 $(top_builddir)/src/identity/libgnunetidentity.la \
@@ -108,6 +109,7 @@ gnunet_dns2gns_LDADD = \
108 $(top_builddir)/src/dns/libgnunetdnsstub.la \ 109 $(top_builddir)/src/dns/libgnunetdnsstub.la \
109 $(GN_LIBINTL) 110 $(GN_LIBINTL)
110gnunet_dns2gns_DEPENDENCIES = \ 111gnunet_dns2gns_DEPENDENCIES = \
112 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
111 $(top_builddir)/src/util/libgnunetutil.la \ 113 $(top_builddir)/src/util/libgnunetutil.la \
112 $(top_builddir)/src/identity/libgnunetidentity.la \ 114 $(top_builddir)/src/identity/libgnunetidentity.la \
113 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 115 $(top_builddir)/src/namestore/libgnunetnamestore.la \
@@ -156,6 +158,7 @@ gnunet_service_gns_SOURCES = \
156 gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h 158 gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h
157gnunet_service_gns_LDADD = \ 159gnunet_service_gns_LDADD = \
158 -lm \ 160 -lm \
161 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
159 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 162 $(top_builddir)/src/statistics/libgnunetstatistics.la \
160 $(top_builddir)/src/util/libgnunetutil.la \ 163 $(top_builddir)/src/util/libgnunetutil.la \
161 $(top_builddir)/src/dns/libgnunetdns.la \ 164 $(top_builddir)/src/dns/libgnunetdns.la \
@@ -166,6 +169,7 @@ gnunet_service_gns_LDADD = \
166 $(USE_VPN) \ 169 $(USE_VPN) \
167 $(GN_LIBINTL) 170 $(GN_LIBINTL)
168gnunet_service_gns_DEPENDENCIES = \ 171gnunet_service_gns_DEPENDENCIES = \
172 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
169 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 173 $(top_builddir)/src/statistics/libgnunetstatistics.la \
170 $(top_builddir)/src/util/libgnunetutil.la \ 174 $(top_builddir)/src/util/libgnunetutil.la \
171 $(top_builddir)/src/dns/libgnunetdns.la \ 175 $(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
15 XLIBS = -lgcov 15 XLIBS = -lgcov
16endif 16endif
17 17
18check_PROGRAMS = \
19 test_gnsrecord_crypto \
20 test_gnsrecord_serialization
21
18if ENABLE_TEST_RUN 22if ENABLE_TEST_RUN
19TESTS = \ 23TESTS = \
20 $(check_PROGRAMS) \ 24 $(check_PROGRAMS) \
@@ -25,7 +29,10 @@ lib_LTLIBRARIES = \
25 libgnunetgnsrecord.la 29 libgnunetgnsrecord.la
26 30
27libgnunetgnsrecord_la_SOURCES = \ 31libgnunetgnsrecord_la_SOURCES = \
28 gnsrecord.c 32 gnsrecord.c \
33 gnsrecord_serialization.c \
34 gnsrecord_crypto.c \
35 gnsrecord_misc.c
29libgnunetgnsrecord_la_LIBADD = \ 36libgnunetgnsrecord_la_LIBADD = \
30 $(top_builddir)/src/dns/libgnunetdnsparser.la \ 37 $(top_builddir)/src/dns/libgnunetdnsparser.la \
31 $(top_builddir)/src/util/libgnunetutil.la \ 38 $(top_builddir)/src/util/libgnunetutil.la \
@@ -52,3 +59,17 @@ libgnunet_plugin_gnsrecord_dns_la_LDFLAGS = \
52EXTRA_DIST = \ 59EXTRA_DIST = \
53 $(check_SCRIPTS) 60 $(check_SCRIPTS)
54 61
62test_gnsrecord_serialization_SOURCES = \
63 test_gnsrecord_serialization.c
64test_gnsrecord_serialization_LDADD = \
65 $(top_builddir)/src/testing/libgnunettesting.la \
66 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
67 $(top_builddir)/src/util/libgnunetutil.la
68
69test_gnsrecord_crypto_SOURCES = \
70 test_gnsrecord_crypto.c
71test_gnsrecord_crypto_LDADD = \
72 $(top_builddir)/src/testing/libgnunettesting.la \
73 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
74 $(top_builddir)/src/util/libgnunetutil.la
75
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 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file gnsrecord/gnsrecord_crypto.c
23 * @brief API for GNS record-related crypto
24 * @author Martin Schanzenbach
25 * @author Matthias Wachs
26 * @author Christian Grothoff
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_signatures.h"
32#include "gnunet_arm_service.h"
33#include "gnunet_gnsrecord_lib.h"
34#include "gnunet_dnsparser_lib.h"
35#include "gnunet_tun_lib.h"
36
37
38#define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__)
39
40
41/**
42 * Derive session key and iv from label and public key.
43 *
44 * @param iv initialization vector to initialize
45 * @param skey session key to initialize
46 * @param label label to use for KDF
47 * @param pub public key to use for KDF
48 */
49static void
50derive_block_aes_key (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
51 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
52 const char *label,
53 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
54{
55 static const char ctx_key[] = "gns-aes-ctx-key";
56 static const char ctx_iv[] = "gns-aes-ctx-iv";
57
58 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
59 pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
60 label, strlen (label),
61 ctx_key, strlen (ctx_key),
62 NULL, 0);
63 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
64 pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
65 label, strlen (label),
66 ctx_iv, strlen (ctx_iv),
67 NULL, 0);
68}
69
70
71/**
72 * Sign name and records
73 *
74 * @param key the private key
75 * @param expire block expiration
76 * @param label the name for the records
77 * @param rd record data
78 * @param rd_count number of records
79 * @return NULL on error (block too large)
80 */
81struct GNUNET_NAMESTORE_Block *
82GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
83 struct GNUNET_TIME_Absolute expire,
84 const char *label,
85 const struct GNUNET_NAMESTORE_RecordData *rd,
86 unsigned int rd_count)
87{
88 size_t payload_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
89 char payload[sizeof (uint32_t) + payload_len];
90 struct GNUNET_NAMESTORE_Block *block;
91 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
92 struct GNUNET_CRYPTO_EcdsaPrivateKey *dkey;
93 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
94 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
95 uint32_t rd_count_nbo;
96
97 if (payload_len > GNUNET_NAMESTORE_MAX_VALUE_SIZE)
98 return NULL;
99 rd_count_nbo = htonl (rd_count);
100 memcpy (payload, &rd_count_nbo, sizeof (uint32_t));
101 GNUNET_assert (payload_len ==
102 GNUNET_NAMESTORE_records_serialize (rd_count, rd,
103 payload_len, &payload[sizeof (uint32_t)]));
104 block = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Block) +
105 sizeof (uint32_t) + payload_len);
106 block->purpose.size = htonl (sizeof (uint32_t) + payload_len +
107 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
108 sizeof (struct GNUNET_TIME_AbsoluteNBO));
109 block->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
110 block->expiration_time = GNUNET_TIME_absolute_hton (expire);
111 dkey = GNUNET_CRYPTO_ecdsa_private_key_derive (key,
112 label,
113 "gns");
114 GNUNET_CRYPTO_ecdsa_key_get_public (dkey,
115 &block->derived_key);
116 GNUNET_CRYPTO_ecdsa_key_get_public (key,
117 &pkey);
118 derive_block_aes_key (&iv, &skey, label, &pkey);
119 GNUNET_break (payload_len + sizeof (uint32_t) ==
120 GNUNET_CRYPTO_symmetric_encrypt (payload, payload_len + sizeof (uint32_t),
121 &skey, &iv,
122 &block[1]));
123 if (GNUNET_OK !=
124 GNUNET_CRYPTO_ecdsa_sign (dkey,
125 &block->purpose,
126 &block->signature))
127 {
128 GNUNET_break (0);
129 GNUNET_free (dkey);
130 GNUNET_free (block);
131 return NULL;
132 }
133 GNUNET_free (dkey);
134 return block;
135}
136
137
138/**
139 * Check if a signature is valid. This API is used by the GNS Block
140 * to validate signatures received from the network.
141 *
142 * @param block block to verify
143 * @return #GNUNET_OK if the signature is valid
144 */
145int
146GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block)
147{
148 return GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN,
149 &block->purpose,
150 &block->signature,
151 &block->derived_key);
152}
153
154
155/**
156 * Decrypt block.
157 *
158 * @param block block to decrypt
159 * @param zone_key public key of the zone
160 * @param label the name for the records
161 * @param proc function to call with the result
162 * @param proc_cls closure for proc
163 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was
164 * not well-formed
165 */
166int
167GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block,
168 const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key,
169 const char *label,
170 GNUNET_NAMESTORE_RecordCallback proc,
171 void *proc_cls)
172{
173 size_t payload_len = ntohl (block->purpose.size) -
174 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) -
175 sizeof (struct GNUNET_TIME_AbsoluteNBO);
176 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
177 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
178
179 if (ntohl (block->purpose.size) <
180 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
181 sizeof (struct GNUNET_TIME_AbsoluteNBO))
182 {
183 GNUNET_break_op (0);
184 return GNUNET_SYSERR;
185 }
186 derive_block_aes_key (&iv, &skey, label, zone_key);
187 {
188 char payload[payload_len];
189 uint32_t rd_count;
190
191 GNUNET_break (payload_len ==
192 GNUNET_CRYPTO_symmetric_decrypt (&block[1], payload_len,
193 &skey, &iv,
194 payload));
195 memcpy (&rd_count,
196 payload,
197 sizeof (uint32_t));
198 rd_count = ntohl (rd_count);
199 if (rd_count > 2048)
200 {
201 /* limit to sane value */
202 GNUNET_break_op (0);
203 return GNUNET_SYSERR;
204 }
205 {
206 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
207
208 if (GNUNET_OK !=
209 GNUNET_NAMESTORE_records_deserialize (payload_len - sizeof (uint32_t),
210 &payload[sizeof (uint32_t)],
211 rd_count,
212 rd))
213 {
214 GNUNET_break_op (0);
215 return GNUNET_SYSERR;
216 }
217 if (NULL != proc)
218 proc (proc_cls, rd_count, (0 != rd_count) ? rd : NULL);
219 }
220 }
221 return GNUNET_OK;
222}
223
224
225/**
226 * Calculate the DHT query for a given @a label in a given @a zone.
227 *
228 * @param zone private key of the zone
229 * @param label label of the record
230 * @param query hash to use for the query
231 */
232void
233GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
234 const char *label,
235 struct GNUNET_HashCode *query)
236{
237 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
238
239 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &pub);
240 GNUNET_NAMESTORE_query_from_public_key (&pub, label, query);
241}
242
243
244/**
245 * Calculate the DHT query for a given @a label in a given @a zone.
246 *
247 * @param pub public key of the zone
248 * @param label label of the record
249 * @param query hash to use for the query
250 */
251void
252GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
253 const char *label,
254 struct GNUNET_HashCode *query)
255{
256 struct GNUNET_CRYPTO_EcdsaPublicKey pd;
257
258 GNUNET_CRYPTO_ecdsa_public_key_derive (pub, label, "gns", &pd);
259 GNUNET_CRYPTO_hash (&pd, sizeof (pd), query);
260}
261
262
263/* 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 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file gnsrecord/gnsrecord_misc.c
23 * @brief MISC functions related to GNS records
24 * @author Martin Schanzenbach
25 * @author Matthias Wachs
26 * @author Christian Grothoff
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_signatures.h"
32#include "gnunet_arm_service.h"
33#include "gnunet_gnsrecord_lib.h"
34#include "gnunet_dnsparser_lib.h"
35#include "gnunet_tun_lib.h"
36
37
38#define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__)
39
40/**
41 * Convert a UTF-8 string to UTF-8 lowercase
42 * @param src source string
43 * @return converted result
44 */
45char *
46GNUNET_NAMESTORE_normalize_string (const char *src)
47{
48 GNUNET_assert (NULL != src);
49 char *res = strdup (src);
50 /* normalize */
51 GNUNET_STRINGS_utf8_tolower(src, &res);
52 return res;
53}
54
55
56/**
57 * Convert a zone key to a string (for printing debug messages).
58 * This is one of the very few calls in the entire API that is
59 * NOT reentrant!
60 *
61 * @param z the zone key
62 * @return string form; will be overwritten by next call to #GNUNET_NAMESTORE_z2s
63 */
64const char *
65GNUNET_NAMESTORE_z2s (const struct GNUNET_CRYPTO_EcdsaPublicKey *z)
66{
67 static char buf[sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) * 8];
68 char *end;
69
70 end = GNUNET_STRINGS_data_to_string ((const unsigned char *) z,
71 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
72 buf, sizeof (buf));
73 if (NULL == end)
74 {
75 GNUNET_break (0);
76 return NULL;
77 }
78 *end = '\0';
79 return buf;
80}
81
82
83/**
84 * Compares if two records are equal (ignoring flags such
85 * as authority, private and pending, but not relative vs.
86 * absolute expiration time).
87 *
88 * @param a record
89 * @param b record
90 * @return #GNUNET_YES if the records are equal or #GNUNET_NO if they are not
91 */
92int
93GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a,
94 const struct GNUNET_NAMESTORE_RecordData *b)
95{
96 LOG (GNUNET_ERROR_TYPE_DEBUG,
97 "Comparing records\n");
98 if (a->record_type != b->record_type)
99 {
100 LOG (GNUNET_ERROR_TYPE_DEBUG,
101 "Record type %lu != %lu\n", a->record_type, b->record_type);
102 return GNUNET_NO;
103 }
104 if ((a->expiration_time != b->expiration_time) &&
105 ((a->expiration_time != 0) && (b->expiration_time != 0)))
106 {
107 LOG (GNUNET_ERROR_TYPE_DEBUG,
108 "Expiration time %llu != %llu\n",
109 a->expiration_time,
110 b->expiration_time);
111 return GNUNET_NO;
112 }
113 if ((a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS)
114 != (b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS))
115 {
116 LOG (GNUNET_ERROR_TYPE_DEBUG,
117 "Flags %lu (%lu) != %lu (%lu)\n", a->flags,
118 a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS, b->flags,
119 b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS);
120 return GNUNET_NO;
121 }
122 if (a->data_size != b->data_size)
123 {
124 LOG (GNUNET_ERROR_TYPE_DEBUG,
125 "Data size %lu != %lu\n",
126 a->data_size,
127 b->data_size);
128 return GNUNET_NO;
129 }
130 if (0 != memcmp (a->data, b->data, a->data_size))
131 {
132 LOG (GNUNET_ERROR_TYPE_DEBUG,
133 "Data contents do not match\n");
134 return GNUNET_NO;
135 }
136 LOG (GNUNET_ERROR_TYPE_DEBUG,
137 "Records are equal\n");
138 return GNUNET_YES;
139}
140
141
142/**
143 * Returns the expiration time of the given block of records. The block
144 * expiration time is the expiration time of the record with smallest
145 * expiration time.
146 *
147 * @param rd_count number of records given in @a rd
148 * @param rd array of records
149 * @return absolute expiration time
150 */
151struct GNUNET_TIME_Absolute
152GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count,
153 const struct GNUNET_NAMESTORE_RecordData *rd)
154{
155 unsigned int c;
156 struct GNUNET_TIME_Absolute expire;
157 struct GNUNET_TIME_Absolute at;
158 struct GNUNET_TIME_Relative rt;
159
160 if (NULL == rd)
161 return GNUNET_TIME_UNIT_ZERO_ABS;
162 expire = GNUNET_TIME_UNIT_FOREVER_ABS;
163 for (c = 0; c < rd_count; c++)
164 {
165 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
166 {
167 rt.rel_value_us = rd[c].expiration_time;
168 at = GNUNET_TIME_relative_to_absolute (rt);
169 }
170 else
171 {
172 at.abs_value_us = rd[c].expiration_time;
173 }
174 expire = GNUNET_TIME_absolute_min (at, expire);
175 }
176 LOG (GNUNET_ERROR_TYPE_DEBUG,
177 "Determined expiration time for block with %u records to be %s\n",
178 rd_count,
179 GNUNET_STRINGS_absolute_time_to_string (expire));
180 return expire;
181}
182
183
184/**
185 * Test if a given record is expired.
186 *
187 * @return #GNUNET_YES if the record is expired,
188 * #GNUNET_NO if not
189 */
190int
191GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd)
192{
193 struct GNUNET_TIME_Absolute at;
194
195 if (0 != (rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
196 return GNUNET_NO;
197 at.abs_value_us = rd->expiration_time;
198 return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value_us) ? GNUNET_YES : GNUNET_NO;
199}
200
201
202/**
203 * Convert public key to the respective absolute domain name in the
204 * ".zkey" pTLD.
205 * This is one of the very few calls in the entire API that is
206 * NOT reentrant!
207 *
208 * @param pkey a public key with a point on the eliptic curve
209 * @return string "X.zkey" where X is the public
210 * key in an encoding suitable for DNS labels.
211 */
212const char *
213GNUNET_NAMESTORE_pkey_to_zkey (const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey)
214{
215 static char ret[128];
216 char *pkeys;
217
218 pkeys = GNUNET_CRYPTO_ecdsa_public_key_to_string (pkey);
219 GNUNET_snprintf (ret,
220 sizeof (ret),
221 "%s.zkey",
222 pkeys);
223 GNUNET_free (pkeys);
224 return ret;
225}
226
227
228/**
229 * Convert an absolute domain name in the ".zkey" pTLD to the
230 * respective public key.
231 *
232 * @param zkey string "X.zkey" where X is the coordinates of the public
233 * key in an encoding suitable for DNS labels.
234 * @param pkey set to a public key on the eliptic curve
235 * @return #GNUNET_SYSERR if @a zkey has the wrong syntax
236 */
237int
238GNUNET_NAMESTORE_zkey_to_pkey (const char *zkey,
239 struct GNUNET_CRYPTO_EcdsaPublicKey *pkey)
240{
241 char *cpy;
242 char *dot;
243 const char *x;
244
245 cpy = GNUNET_strdup (zkey);
246 x = cpy;
247 if (NULL == (dot = strchr (x, (int) '.')))
248 goto error;
249 *dot = '\0';
250 if (0 != strcasecmp (dot + 1,
251 "zkey"))
252 goto error;
253
254 if (GNUNET_OK !=
255 GNUNET_CRYPTO_ecdsa_public_key_from_string (x,
256 strlen (x),
257 pkey))
258 goto error;
259 GNUNET_free (cpy);
260 return GNUNET_OK;
261 error:
262 GNUNET_free (cpy);
263 return GNUNET_SYSERR;
264}
265
266
267/* 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 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file gnsrecord/gnsrecord_serialization.c
23 * @brief API to serialize and deserialize GNS records
24 * @author Martin Schanzenbach
25 * @author Matthias Wachs
26 * @author Christian Grothoff
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_signatures.h"
32#include "gnunet_arm_service.h"
33#include "gnunet_gnsrecord_lib.h"
34#include "gnunet_dnsparser_lib.h"
35#include "gnunet_tun_lib.h"
36
37
38#define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__)
39
40GNUNET_NETWORK_STRUCT_BEGIN
41
42
43/**
44 * Internal format of a record in the serialized form.
45 */
46struct NetworkRecord
47{
48
49 /**
50 * Expiration time for the DNS record; relative or absolute depends
51 * on 'flags', network byte order.
52 */
53 uint64_t expiration_time GNUNET_PACKED;
54
55 /**
56 * Number of bytes in 'data', network byte order.
57 */
58 uint32_t data_size GNUNET_PACKED;
59
60 /**
61 * Type of the GNS/DNS record, network byte order.
62 */
63 uint32_t record_type GNUNET_PACKED;
64
65 /**
66 * Flags for the record, network byte order.
67 */
68 uint32_t flags GNUNET_PACKED;
69
70};
71
72GNUNET_NETWORK_STRUCT_END
73
74
75/**
76 * Calculate how many bytes we will need to serialize the given
77 * records.
78 *
79 * @param rd_count number of records in the rd array
80 * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
81 * @return the required size to serialize
82 */
83size_t
84GNUNET_NAMESTORE_records_get_size (unsigned int rd_count,
85 const struct GNUNET_NAMESTORE_RecordData *rd)
86{
87 unsigned int i;
88 size_t ret;
89
90 ret = sizeof (struct NetworkRecord) * rd_count;
91 for (i=0;i<rd_count;i++)
92 {
93 GNUNET_assert ((ret + rd[i].data_size) >= ret);
94 ret += rd[i].data_size;
95 }
96 return ret;
97}
98
99
100/**
101 * Serialize the given records to the given destination buffer.
102 *
103 * @param rd_count number of records in the rd array
104 * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
105 * @param dest_size size of the destination array
106 * @param dest where to write the result
107 * @return the size of serialized records, -1 if records do not fit
108 */
109ssize_t
110GNUNET_NAMESTORE_records_serialize (unsigned int rd_count,
111 const struct GNUNET_NAMESTORE_RecordData *rd,
112 size_t dest_size,
113 char *dest)
114{
115 struct NetworkRecord rec;
116 unsigned int i;
117 size_t off;
118
119 off = 0;
120 for (i=0;i<rd_count;i++)
121 {
122 LOG (GNUNET_ERROR_TYPE_DEBUG,
123 "Serializing record %u with flags %d and expiration time %llu\n",
124 i,
125 rd[i].flags,
126 (unsigned long long) rd[i].expiration_time);
127 rec.expiration_time = GNUNET_htonll (rd[i].expiration_time);
128 rec.data_size = htonl ((uint32_t) rd[i].data_size);
129 rec.record_type = htonl (rd[i].record_type);
130 rec.flags = htonl (rd[i].flags);
131 if (off + sizeof (rec) > dest_size)
132 return -1;
133 memcpy (&dest[off], &rec, sizeof (rec));
134 off += sizeof (rec);
135 if (off + rd[i].data_size > dest_size)
136 return -1;
137 memcpy (&dest[off], rd[i].data, rd[i].data_size);
138 off += rd[i].data_size;
139 }
140 return off;
141}
142
143
144/**
145 * Deserialize the given records to the given destination.
146 *
147 * @param len size of the serialized record data
148 * @param src the serialized record data
149 * @param rd_count number of records in the rd array
150 * @param dest where to put the data
151 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
152 */
153int
154GNUNET_NAMESTORE_records_deserialize (size_t len,
155 const char *src,
156 unsigned int rd_count,
157 struct GNUNET_NAMESTORE_RecordData *dest)
158{
159 struct NetworkRecord rec;
160 unsigned int i;
161 size_t off;
162
163 off = 0;
164 for (i=0;i<rd_count;i++)
165 {
166 if (off + sizeof (rec) > len)
167 return GNUNET_SYSERR;
168 memcpy (&rec, &src[off], sizeof (rec));
169 dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time);
170 dest[i].data_size = ntohl ((uint32_t) rec.data_size);
171 dest[i].record_type = ntohl (rec.record_type);
172 dest[i].flags = ntohl (rec.flags);
173 off += sizeof (rec);
174 if (off + dest[i].data_size > len)
175 return GNUNET_SYSERR;
176 dest[i].data = &src[off];
177 off += dest[i].data_size;
178 LOG (GNUNET_ERROR_TYPE_DEBUG,
179 "Deserialized record %u with flags %d and expiration time %llu\n",
180 i,
181 dest[i].flags,
182 (unsigned long long) dest[i].expiration_time);
183 }
184 return GNUNET_OK;
185}
186
187
188/* end of gnsrecord_serialization.c */
diff --git a/src/namestore/test_namestore_api_blocks.c b/src/gnsrecord/test_gnsrecord_crypto.c
index 001e7e182..345bf353b 100644
--- a/src/namestore/test_namestore_api_blocks.c
+++ b/src/gnsrecord/test_gnsrecord_crypto.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors) 3 (C) 2013 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -18,12 +18,12 @@
18 Boston, MA 02111-1307, USA. 18 Boston, MA 02111-1307, USA.
19*/ 19*/
20/** 20/**
21 * @file namestore/test_namestore_api_blocks.c 21 * @file gnsrecord/test_gnsrecord_crypto.c
22 * @brief testcase for block creation, verification and decryption 22 * @brief testcase for block creation, verification and decryption
23 */ 23 */
24#include "platform.h" 24#include "platform.h"
25#include "gnunet_namestore_service.h" 25#include "gnunet_util_lib.h"
26#include "namestore.h" 26#include "gnunet_gnsrecord_lib.h"
27 27
28#define RECORDS 5 28#define RECORDS 5
29 29
@@ -129,9 +129,7 @@ run (void *cls, char *const *args, const char *cfgfile,
129int 129int
130main (int argc, char *argv[]) 130main (int argc, char *argv[])
131{ 131{
132 static char *const argvx[] = { "test-namestore-api", 132 static char *const argvx[] = { "test-gnsrecord-crypto",
133 "-c",
134 "test_namestore_api.conf",
135 NULL 133 NULL
136 }; 134 };
137 static struct GNUNET_GETOPT_CommandLineOption options[] = { 135 static struct GNUNET_GETOPT_CommandLineOption options[] = {
@@ -144,4 +142,4 @@ main (int argc, char *argv[])
144 return res; 142 return res;
145} 143}
146 144
147/* end of test_namestore_api_blocks.c */ 145/* end of test_gnsrecord_crypto.c */
diff --git a/src/namestore/test_namestore_record_serialization.c b/src/gnsrecord/test_gnsrecord_serialization.c
index 288ecb841..de6a7ba1d 100644
--- a/src/namestore/test_namestore_record_serialization.c
+++ b/src/gnsrecord/test_gnsrecord_serialization.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors) 3 (C) 2013 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -18,13 +18,12 @@
18 Boston, MA 02111-1307, USA. 18 Boston, MA 02111-1307, USA.
19*/ 19*/
20/** 20/**
21 * @file namestore/test_namestore_record_serialization.c 21 * @file gnsrecord/test_gnsrecord_serialization.c
22 * @brief testcase for test_namestore_record_serialization.c 22 * @brief testcase for gnsrecord_serialization.c
23 */ 23 */
24#include "platform.h" 24#include "platform.h"
25#include "gnunet_util_lib.h" 25#include "gnunet_util_lib.h"
26#include "gnunet_namestore_service.h" 26#include "gnunet_gnsrecord_lib.h"
27#include "namestore.h"
28 27
29#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) 28#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
30 29
@@ -121,12 +120,11 @@ run (void *cls, char *const *args, const char *cfgfile,
121 } 120 }
122} 121}
123 122
124static int 123
125check () 124int
125main (int argcx, char *argvx[])
126{ 126{
127 static char *const argv[] = { "test_namestore_record_serialization", 127 static char *const argv[] = { "test_gnsrecord_serialization",
128 "-c",
129 "test_namestore_api.conf",
130 NULL 128 NULL
131 }; 129 };
132 static struct GNUNET_GETOPT_CommandLineOption options[] = { 130 static struct GNUNET_GETOPT_CommandLineOption options[] = {
@@ -139,14 +137,4 @@ check ()
139 return res; 137 return res;
140} 138}
141 139
142int 140/* end of test_gnsrecord_serialization.c */
143main (int argc, char *argv[])
144{
145 int ret;
146
147 ret = check ();
148
149 return ret;
150}
151
152/* end of test_namestore_record_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"
34#endif 34#endif
35#endif 35#endif
36 36
37/**
38 * Maximum size of a value that can be stored in a GNS block.
39 */
40#define GNUNET_NAMESTORE_MAX_VALUE_SIZE (63 * 1024)
41
37 42
38/** 43/**
39 * Record type indicating any record/'*' 44 * Record type indicating any record/'*'
@@ -76,6 +81,144 @@ extern "C"
76#define GNUNET_GNSRECORD_TYPE_PHONE 65542 81#define GNUNET_GNSRECORD_TYPE_PHONE 65542
77 82
78 83
84/**
85 * Flags that can be set for a record.
86 */
87enum GNUNET_NAMESTORE_RecordFlags
88{
89
90 /**
91 * No special options.
92 */
93 GNUNET_NAMESTORE_RF_NONE = 0,
94
95 /**
96 * This is a private record of this peer and it should
97 * thus not be handed out to other peers.
98 */
99 GNUNET_NAMESTORE_RF_PRIVATE = 2,
100
101 /**
102 * This record was added automatically by the system
103 * and is pending user confimation.
104 */
105 GNUNET_NAMESTORE_RF_PENDING = 4,
106
107 /**
108 * This expiration time of the record is a relative
109 * time (not an absolute time).
110 */
111 GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION = 8,
112
113 /**
114 * This record should not be used unless all (other) records with an absolute
115 * expiration time have expired.
116 */
117 GNUNET_NAMESTORE_RF_SHADOW_RECORD = 16
118
119 /**
120 * When comparing flags for record equality for removal,
121 * which flags should must match (in addition to the type,
122 * name, expiration value and data of the record)? All flags
123 * that are not listed here will be ignored for this purpose.
124 * (for example, we don't expect that users will remember to
125 * pass the '--private' option when removing a record from
126 * the namestore, hence we don't require this particular option
127 * to match upon removal). See also
128 * #GNUNET_NAMESTORE_records_cmp.
129 */
130#define GNUNET_NAMESTORE_RF_RCMP_FLAGS (GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)
131};
132
133
134/**
135 * A GNS record.
136 */
137struct GNUNET_NAMESTORE_RecordData
138{
139
140 /**
141 * Binary value stored in the DNS record. Note: "data" must never
142 * be individually 'malloc'ed, but instead always points into some
143 * existing data area.
144 */
145 const void *data;
146
147 /**
148 * Expiration time for the DNS record. Can be relative
149 * or absolute, depending on 'flags'. Measured in the same
150 * unit as GNUnet time (microseconds).
151 */
152 uint64_t expiration_time;
153
154 /**
155 * Number of bytes in 'data'.
156 */
157 size_t data_size;
158
159 /**
160 * Type of the GNS/DNS record.
161 */
162 uint32_t record_type;
163
164 /**
165 * Flags for the record.
166 */
167 enum GNUNET_NAMESTORE_RecordFlags flags;
168};
169
170
171
172GNUNET_NETWORK_STRUCT_BEGIN
173
174
175/**
176 * Information we have in an encrypted block with record data (i.e. in the DHT).
177 */
178struct GNUNET_NAMESTORE_Block
179{
180
181 /**
182 * Signature of the block.
183 */
184 struct GNUNET_CRYPTO_EcdsaSignature signature;
185
186 /**
187 * Derived key used for signing; hash of this is the query.
188 */
189 struct GNUNET_CRYPTO_EcdsaPublicKey derived_key;
190
191 /**
192 * Number of bytes signed; also specifies the number of bytes
193 * of encrypted data that follow.
194 */
195 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
196
197 /**
198 * Expiration time of the block.
199 */
200 struct GNUNET_TIME_AbsoluteNBO expiration_time;
201
202 /* followed by encrypted data */
203};
204
205GNUNET_NETWORK_STRUCT_END
206
207
208/**
209 * Process a records that were decrypted from a block.
210 *
211 * @param cls closure
212 * @param rd_count number of entries in @a rd array
213 * @param rd array of records with data to store
214 */
215typedef void (*GNUNET_NAMESTORE_RecordCallback) (void *cls,
216 unsigned int rd_count,
217 const struct GNUNET_NAMESTORE_RecordData *rd);
218
219
220
221/* ***************** API related to GNSRECORD plugins ************** */
79 222
80/** 223/**
81 * Convert the binary value @a data of a record of 224 * Convert the binary value @a data of a record of
@@ -129,6 +272,217 @@ const char *
129GNUNET_GNSRECORD_number_to_typename (uint32_t type); 272GNUNET_GNSRECORD_number_to_typename (uint32_t type);
130 273
131 274
275/* convenience APIs for serializing / deserializing GNS records */
276
277/**
278 * Calculate how many bytes we will need to serialize the given
279 * records.
280 *
281 * @param rd_count number of records in the @a rd array
282 * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
283 * @return the required size to serialize
284 */
285size_t
286GNUNET_NAMESTORE_records_get_size (unsigned int rd_count,
287 const struct GNUNET_NAMESTORE_RecordData *rd);
288
289
290/**
291 * Serialize the given records to the given destination buffer.
292 *
293 * @param rd_count number of records in the @a rd array
294 * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
295 * @param dest_size size of the destination array @a dst
296 * @param dest where to write the result
297 * @return the size of serialized records, -1 if records do not fit
298 */
299ssize_t
300GNUNET_NAMESTORE_records_serialize (unsigned int rd_count,
301 const struct GNUNET_NAMESTORE_RecordData *rd,
302 size_t dest_size,
303 char *dest);
304
305
306/**
307 * Deserialize the given records to the given destination.
308 *
309 * @param len size of the serialized record data
310 * @param src the serialized record data
311 * @param rd_count number of records in the @a dest array
312 * @param dest where to put the data
313 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
314 */
315int
316GNUNET_NAMESTORE_records_deserialize (size_t len,
317 const char *src,
318 unsigned int rd_count,
319 struct GNUNET_NAMESTORE_RecordData *dest);
320
321
322/* ******* general APIs relating to blocks, records and labels ******** */
323
324
325
326/**
327 * Test if a given record is expired.
328 *
329 * @param rd record to test
330 * @return #GNUNET_YES if the record is expired,
331 * #GNUNET_NO if not
332 */
333int
334GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd);
335
336
337/**
338 * Convert a UTF-8 string to UTF-8 lowercase
339 * @param src source string
340 * @return converted result
341 */
342char *
343GNUNET_NAMESTORE_normalize_string (const char *src);
344
345
346/**
347 * Convert a zone to a string (for printing debug messages).
348 * This is one of the very few calls in the entire API that is
349 * NOT reentrant!
350 *
351 * @param z public key of a zone
352 * @return string form; will be overwritten by next call to #GNUNET_NAMESTORE_z2s.
353 */
354const char *
355GNUNET_NAMESTORE_z2s (const struct GNUNET_CRYPTO_EcdsaPublicKey *z);
356
357
358/**
359 * Convert public key to the respective absolute domain name in the
360 * ".zkey" pTLD.
361 * This is one of the very few calls in the entire API that is
362 * NOT reentrant!
363 *
364 * @param pkey a public key with a point on the eliptic curve
365 * @return string "X.zkey" where X is the coordinates of the public
366 * key in an encoding suitable for DNS labels.
367 */
368const char *
369GNUNET_NAMESTORE_pkey_to_zkey (const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey);
370
371
372/**
373 * Convert an absolute domain name in the ".zkey" pTLD to the
374 * respective public key.
375 *
376 * @param zkey string "X.zkey" where X is the public
377 * key in an encoding suitable for DNS labels.
378 * @param pkey set to a public key on the eliptic curve
379 * @return #GNUNET_SYSERR if @a zkey has the wrong syntax
380 */
381int
382GNUNET_NAMESTORE_zkey_to_pkey (const char *zkey,
383 struct GNUNET_CRYPTO_EcdsaPublicKey *pkey);
384
385
386/**
387 * Calculate the DHT query for a given @a label in a given @a zone.
388 *
389 * @param zone private key of the zone
390 * @param label label of the record
391 * @param query hash to use for the query
392 */
393void
394GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
395 const char *label,
396 struct GNUNET_HashCode *query);
397
398
399/**
400 * Calculate the DHT query for a given @a label in a given @a zone.
401 *
402 * @param pub public key of the zone
403 * @param label label of the record
404 * @param query hash to use for the query
405 */
406void
407GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
408 const char *label,
409 struct GNUNET_HashCode *query);
410
411
412/**
413 * Sign name and records
414 *
415 * @param key the private key
416 * @param expire block expiration
417 * @param label the name for the records
418 * @param rd record data
419 * @param rd_count number of records in @a rd
420 */
421struct GNUNET_NAMESTORE_Block *
422GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
423 struct GNUNET_TIME_Absolute expire,
424 const char *label,
425 const struct GNUNET_NAMESTORE_RecordData *rd,
426 unsigned int rd_count);
427
428
429/**
430 * Check if a signature is valid. This API is used by the GNS Block
431 * to validate signatures received from the network.
432 *
433 * @param block block to verify
434 * @return #GNUNET_OK if the signature is valid
435 */
436int
437GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block);
438
439
440/**
441 * Decrypt block.
442 *
443 * @param block block to decrypt
444 * @param zone_key public key of the zone
445 * @param label the name for the records
446 * @param proc function to call with the result
447 * @param proc_cls closure for @a proc
448 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was
449 * not well-formed
450 */
451int
452GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block,
453 const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key,
454 const char *label,
455 GNUNET_NAMESTORE_RecordCallback proc,
456 void *proc_cls);
457
458
459/**
460 * Compares if two records are equal
461 *
462 * @param a a record
463 * @param b another record
464 * @return #GNUNET_YES if the records are equal, or #GNUNET_NO if not.
465 */
466int
467GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a,
468 const struct GNUNET_NAMESTORE_RecordData *b);
469
470
471/**
472 * Returns the expiration time of the given block of records. The block
473 * expiration time is the expiration time of the record with smallest
474 * expiration time.
475 *
476 * @param rd_count number of records given in @a rd
477 * @param rd array of records
478 * @return absolute expiration time
479 */
480struct GNUNET_TIME_Absolute
481GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count,
482 const struct GNUNET_NAMESTORE_RecordData *rd);
483
484
485
132#if 0 /* keep Emacsens' auto-indent happy */ 486#if 0 /* keep Emacsens' auto-indent happy */
133{ 487{
134#endif 488#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 @@
31 31
32#include "gnunet_util_lib.h" 32#include "gnunet_util_lib.h"
33#include "gnunet_block_lib.h" 33#include "gnunet_block_lib.h"
34#include "gnunet_gnsrecord_lib.h"
34 35
35#ifdef __cplusplus 36#ifdef __cplusplus
36extern "C" 37extern "C"
@@ -56,11 +57,6 @@ struct GNUNET_NAMESTORE_Handle;
56 */ 57 */
57struct GNUNET_NAMESTORE_ZoneIterator; 58struct GNUNET_NAMESTORE_ZoneIterator;
58 59
59/**
60 * Maximum size of a value that can be stored in the namestore.
61 */
62#define GNUNET_NAMESTORE_MAX_VALUE_SIZE (63 * 1024)
63
64 60
65/** 61/**
66 * Connect to the namestore service. 62 * Connect to the namestore service.
@@ -99,131 +95,6 @@ typedef void (*GNUNET_NAMESTORE_ContinuationWithStatus) (void *cls,
99 95
100 96
101/** 97/**
102 * Flags that can be set for a record.
103 */
104enum GNUNET_NAMESTORE_RecordFlags
105{
106
107 /**
108 * No special options.
109 */
110 GNUNET_NAMESTORE_RF_NONE = 0,
111
112 /**
113 * This is a private record of this peer and it should
114 * thus not be handed out to other peers.
115 */
116 GNUNET_NAMESTORE_RF_PRIVATE = 2,
117
118 /**
119 * This record was added automatically by the system
120 * and is pending user confimation.
121 */
122 GNUNET_NAMESTORE_RF_PENDING = 4,
123
124 /**
125 * This expiration time of the record is a relative
126 * time (not an absolute time).
127 */
128 GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION = 8,
129
130 /**
131 * This record should not be used unless all (other) records with an absolute
132 * expiration time have expired.
133 */
134 GNUNET_NAMESTORE_RF_SHADOW_RECORD = 16
135
136 /**
137 * When comparing flags for record equality for removal,
138 * which flags should must match (in addition to the type,
139 * name, expiration value and data of the record)? All flags
140 * that are not listed here will be ignored for this purpose.
141 * (for example, we don't expect that users will remember to
142 * pass the '--private' option when removing a record from
143 * the namestore, hence we don't require this particular option
144 * to match upon removal). See also
145 * #GNUNET_NAMESTORE_records_cmp.
146 */
147#define GNUNET_NAMESTORE_RF_RCMP_FLAGS (GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)
148};
149
150
151/**
152 * A GNS record.
153 */
154struct GNUNET_NAMESTORE_RecordData
155{
156
157 /**
158 * Binary value stored in the DNS record. Note: "data" must never
159 * be individually 'malloc'ed, but instead always points into some
160 * existing data area.
161 */
162 const void *data;
163
164 /**
165 * Expiration time for the DNS record. Can be relative
166 * or absolute, depending on 'flags'. Measured in the same
167 * unit as GNUnet time (microseconds).
168 */
169 uint64_t expiration_time;
170
171 /**
172 * Number of bytes in 'data'.
173 */
174 size_t data_size;
175
176 /**
177 * Type of the GNS/DNS record.
178 */
179 uint32_t record_type;
180
181 /**
182 * Flags for the record.
183 */
184 enum GNUNET_NAMESTORE_RecordFlags flags;
185};
186
187
188
189GNUNET_NETWORK_STRUCT_BEGIN
190
191
192/**
193 * Information we have in an encrypted block with record data (i.e. in the DHT).
194 */
195struct GNUNET_NAMESTORE_Block
196{
197
198 /**
199 * Signature of the block.
200 */
201 struct GNUNET_CRYPTO_EcdsaSignature signature;
202
203 /**
204 * Derived key used for signing; hash of this is the query.
205 */
206 struct GNUNET_CRYPTO_EcdsaPublicKey derived_key;
207
208 /**
209 * Number of bytes signed; also specifies the number of bytes
210 * of encrypted data that follow.
211 */
212 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
213
214 /**
215 * Expiration time of the block.
216 */
217 struct GNUNET_TIME_AbsoluteNBO expiration_time;
218
219 /* followed by encrypted data */
220};
221
222
223
224GNUNET_NETWORK_STRUCT_END
225
226/**
227 * Store an item in the namestore. If the item is already present, 98 * Store an item in the namestore. If the item is already present,
228 * it is replaced with the new record. 99 * it is replaced with the new record.
229 * 100 *
@@ -329,18 +200,6 @@ GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h,
329 200
330 201
331/** 202/**
332 * Process a records that were decrypted from a block.
333 *
334 * @param cls closure
335 * @param rd_count number of entries in @a rd array
336 * @param rd array of records with data to store
337 */
338typedef void (*GNUNET_NAMESTORE_RecordCallback) (void *cls,
339 unsigned int rd_count,
340 const struct GNUNET_NAMESTORE_RecordData *rd);
341
342
343/**
344 * Cancel a namestore operation. The final callback from the 203 * Cancel a namestore operation. The final callback from the
345 * operation must not have been done yet. Must be called on any 204 * operation must not have been done yet. Must be called on any
346 * namestore operation that has not yet completed prior to calling 205 * namestore operation that has not yet completed prior to calling
@@ -445,211 +304,6 @@ void
445GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm); 304GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm);
446 305
447 306
448/* convenience APIs for serializing / deserializing GNS records */
449
450/**
451 * Calculate how many bytes we will need to serialize the given
452 * records.
453 *
454 * @param rd_count number of records in the @a rd array
455 * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
456 * @return the required size to serialize
457 */
458size_t
459GNUNET_NAMESTORE_records_get_size (unsigned int rd_count,
460 const struct GNUNET_NAMESTORE_RecordData *rd);
461
462
463/**
464 * Serialize the given records to the given destination buffer.
465 *
466 * @param rd_count number of records in the @a rd array
467 * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
468 * @param dest_size size of the destination array @a dst
469 * @param dest where to write the result
470 * @return the size of serialized records, -1 if records do not fit
471 */
472ssize_t
473GNUNET_NAMESTORE_records_serialize (unsigned int rd_count,
474 const struct GNUNET_NAMESTORE_RecordData *rd,
475 size_t dest_size,
476 char *dest);
477
478
479/**
480 * Deserialize the given records to the given destination.
481 *
482 * @param len size of the serialized record data
483 * @param src the serialized record data
484 * @param rd_count number of records in the @a dest array
485 * @param dest where to put the data
486 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
487 */
488int
489GNUNET_NAMESTORE_records_deserialize (size_t len,
490 const char *src,
491 unsigned int rd_count,
492 struct GNUNET_NAMESTORE_RecordData *dest);
493
494
495/**
496 * Test if a given record is expired.
497 *
498 * @param rd record to test
499 * @return #GNUNET_YES if the record is expired,
500 * #GNUNET_NO if not
501 */
502int
503GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd);
504
505
506/**
507 * Convert a UTF-8 string to UTF-8 lowercase
508 * @param src source string
509 * @return converted result
510 */
511char *
512GNUNET_NAMESTORE_normalize_string (const char *src);
513
514
515/**
516 * Convert a zone to a string (for printing debug messages).
517 * This is one of the very few calls in the entire API that is
518 * NOT reentrant!
519 *
520 * @param z public key of a zone
521 * @return string form; will be overwritten by next call to #GNUNET_NAMESTORE_z2s.
522 */
523const char *
524GNUNET_NAMESTORE_z2s (const struct GNUNET_CRYPTO_EcdsaPublicKey *z);
525
526
527/**
528 * Convert public key to the respective absolute domain name in the
529 * ".zkey" pTLD.
530 * This is one of the very few calls in the entire API that is
531 * NOT reentrant!
532 *
533 * @param pkey a public key with a point on the eliptic curve
534 * @return string "X.zkey" where X is the coordinates of the public
535 * key in an encoding suitable for DNS labels.
536 */
537const char *
538GNUNET_NAMESTORE_pkey_to_zkey (const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey);
539
540
541/**
542 * Convert an absolute domain name in the ".zkey" pTLD to the
543 * respective public key.
544 *
545 * @param zkey string "X.zkey" where X is the public
546 * key in an encoding suitable for DNS labels.
547 * @param pkey set to a public key on the eliptic curve
548 * @return #GNUNET_SYSERR if @a zkey has the wrong syntax
549 */
550int
551GNUNET_NAMESTORE_zkey_to_pkey (const char *zkey,
552 struct GNUNET_CRYPTO_EcdsaPublicKey *pkey);
553
554
555/**
556 * Calculate the DHT query for a given @a label in a given @a zone.
557 *
558 * @param zone private key of the zone
559 * @param label label of the record
560 * @param query hash to use for the query
561 */
562void
563GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
564 const char *label,
565 struct GNUNET_HashCode *query);
566
567
568/**
569 * Calculate the DHT query for a given @a label in a given @a zone.
570 *
571 * @param pub public key of the zone
572 * @param label label of the record
573 * @param query hash to use for the query
574 */
575void
576GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
577 const char *label,
578 struct GNUNET_HashCode *query);
579
580
581/**
582 * Sign name and records
583 *
584 * @param key the private key
585 * @param expire block expiration
586 * @param label the name for the records
587 * @param rd record data
588 * @param rd_count number of records in @a rd
589 */
590struct GNUNET_NAMESTORE_Block *
591GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
592 struct GNUNET_TIME_Absolute expire,
593 const char *label,
594 const struct GNUNET_NAMESTORE_RecordData *rd,
595 unsigned int rd_count);
596
597
598/**
599 * Check if a signature is valid. This API is used by the GNS Block
600 * to validate signatures received from the network.
601 *
602 * @param block block to verify
603 * @return #GNUNET_OK if the signature is valid
604 */
605int
606GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block);
607
608
609/**
610 * Decrypt block.
611 *
612 * @param block block to decrypt
613 * @param zone_key public key of the zone
614 * @param label the name for the records
615 * @param proc function to call with the result
616 * @param proc_cls closure for @a proc
617 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was
618 * not well-formed
619 */
620int
621GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block,
622 const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key,
623 const char *label,
624 GNUNET_NAMESTORE_RecordCallback proc,
625 void *proc_cls);
626
627
628/**
629 * Compares if two records are equal
630 *
631 * @param a a record
632 * @param b another record
633 * @return #GNUNET_YES if the records are equal, or #GNUNET_NO if not.
634 */
635int
636GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a,
637 const struct GNUNET_NAMESTORE_RecordData *b);
638
639
640/**
641 * Returns the expiration time of the given block of records. The block
642 * expiration time is the expiration time of the record with smallest
643 * expiration time.
644 *
645 * @param rd_count number of records given in @a rd
646 * @param rd array of records
647 * @return absolute expiration time
648 */
649struct GNUNET_TIME_Absolute
650GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count,
651 const struct GNUNET_NAMESTORE_RecordData *rd);
652
653 307
654#if 0 /* keep Emacsens' auto-indent happy */ 308#if 0 /* keep Emacsens' auto-indent happy */
655{ 309{
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 = \
75gnunet_namecache_SOURCES = \ 75gnunet_namecache_SOURCES = \
76 gnunet-namecache.c 76 gnunet-namecache.c
77gnunet_namecache_LDADD = \ 77gnunet_namecache_LDADD = \
78 $(top_builddir)/src/namestore/libgnunetnamestore.la \
79 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 78 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
80 $(top_builddir)/src/util/libgnunetutil.la \ 79 $(top_builddir)/src/util/libgnunetutil.la \
81 libgnunetnamecache.la \ 80 libgnunetnamecache.la \
@@ -90,7 +89,7 @@ gnunet_service_namecache_SOURCES = \
90 gnunet-service-namecache.c 89 gnunet-service-namecache.c
91 90
92gnunet_service_namecache_LDADD = \ 91gnunet_service_namecache_LDADD = \
93 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 92 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
94 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 93 $(top_builddir)/src/statistics/libgnunetstatistics.la \
95 $(top_builddir)/src/util/libgnunetutil.la \ 94 $(top_builddir)/src/util/libgnunetutil.la \
96 libgnunetnamecache.la \ 95 libgnunetnamecache.la \
@@ -139,7 +138,7 @@ libgnunet_plugin_namecache_postgres_la_DEPENDENCIES = \
139test_namecache_api_cache_block_SOURCES = \ 138test_namecache_api_cache_block_SOURCES = \
140 test_namecache_api_cache_block.c 139 test_namecache_api_cache_block.c
141test_namecache_api_cache_block_LDADD = \ 140test_namecache_api_cache_block_LDADD = \
142 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 141 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
143 $(top_builddir)/src/namecache/libgnunetnamecache.la \ 142 $(top_builddir)/src/namecache/libgnunetnamecache.la \
144 $(top_builddir)/src/testing/libgnunettesting.la \ 143 $(top_builddir)/src/testing/libgnunettesting.la \
145 $(top_builddir)/src/util/libgnunetutil.la 144 $(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
53 53
54if HAVE_SQLITE 54if HAVE_SQLITE
55check_PROGRAMS = \ 55check_PROGRAMS = \
56 test_namestore_record_serialization \
57 test_namestore_api_blocks \
58 $(SQLITE_TESTS) \ 56 $(SQLITE_TESTS) \
59 $(POSTGRES_TESTS) \ 57 $(POSTGRES_TESTS) \
60 $(TESTING_TESTS) 58 $(TESTING_TESTS)
@@ -72,7 +70,6 @@ lib_LTLIBRARIES = \
72libgnunetnamestore_la_SOURCES = \ 70libgnunetnamestore_la_SOURCES = \
73 namestore_api.c \ 71 namestore_api.c \
74 namestore_api_monitor.c \ 72 namestore_api_monitor.c \
75 namestore_api_common.c \
76 namestore.h 73 namestore.h
77libgnunetnamestore_la_LIBADD = \ 74libgnunetnamestore_la_LIBADD = \
78 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 75 $(top_builddir)/src/statistics/libgnunetstatistics.la \
@@ -126,6 +123,7 @@ gnunet_service_namestore_SOURCES = \
126 gnunet-service-namestore.c 123 gnunet-service-namestore.c
127 124
128gnunet_service_namestore_LDADD = \ 125gnunet_service_namestore_LDADD = \
126 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
129 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 127 $(top_builddir)/src/statistics/libgnunetstatistics.la \
130 $(top_builddir)/src/util/libgnunetutil.la \ 128 $(top_builddir)/src/util/libgnunetutil.la \
131 libgnunetnamestore.la \ 129 libgnunetnamestore.la \
@@ -171,18 +169,12 @@ libgnunet_plugin_namestore_postgres_la_DEPENDENCIES = \
171 $(top_builddir)/src/util/libgnunetutil.la \ 169 $(top_builddir)/src/util/libgnunetutil.la \
172 libgnunetnamestore.la 170 libgnunetnamestore.la
173 171
174test_namestore_api_blocks_SOURCES = \
175 test_namestore_api_blocks.c
176test_namestore_api_blocks_LDADD = \
177 $(top_builddir)/src/util/libgnunetutil.la \
178 $(top_builddir)/src/testing/libgnunettesting.la \
179 $(top_builddir)/src/namestore/libgnunetnamestore.la
180
181test_namestore_api_store_SOURCES = \ 172test_namestore_api_store_SOURCES = \
182 test_namestore_api_store.c 173 test_namestore_api_store.c
183test_namestore_api_store_LDADD = \ 174test_namestore_api_store_LDADD = \
184 $(top_builddir)/src/testing/libgnunettesting.la \ 175 $(top_builddir)/src/testing/libgnunettesting.la \
185 $(top_builddir)/src/util/libgnunetutil.la \ 176 $(top_builddir)/src/util/libgnunetutil.la \
177 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
186 $(top_builddir)/src/namestore/libgnunetnamestore.la 178 $(top_builddir)/src/namestore/libgnunetnamestore.la
187 179
188test_namestore_api_store_update_SOURCES = \ 180test_namestore_api_store_update_SOURCES = \
@@ -190,6 +182,7 @@ test_namestore_api_store_update_SOURCES = \
190test_namestore_api_store_update_LDADD = \ 182test_namestore_api_store_update_LDADD = \
191 $(top_builddir)/src/testing/libgnunettesting.la \ 183 $(top_builddir)/src/testing/libgnunettesting.la \
192 $(top_builddir)/src/util/libgnunetutil.la \ 184 $(top_builddir)/src/util/libgnunetutil.la \
185 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
193 $(top_builddir)/src/namestore/libgnunetnamestore.la 186 $(top_builddir)/src/namestore/libgnunetnamestore.la
194 187
195test_namestore_api_cache_block_SOURCES = \ 188test_namestore_api_cache_block_SOURCES = \
@@ -197,6 +190,7 @@ test_namestore_api_cache_block_SOURCES = \
197test_namestore_api_cache_block_LDADD = \ 190test_namestore_api_cache_block_LDADD = \
198 $(top_builddir)/src/testing/libgnunettesting.la \ 191 $(top_builddir)/src/testing/libgnunettesting.la \
199 $(top_builddir)/src/util/libgnunetutil.la \ 192 $(top_builddir)/src/util/libgnunetutil.la \
193 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
200 $(top_builddir)/src/namestore/libgnunetnamestore.la 194 $(top_builddir)/src/namestore/libgnunetnamestore.la
201 195
202test_namestore_api_lookup_public_SOURCES = \ 196test_namestore_api_lookup_public_SOURCES = \
@@ -204,6 +198,7 @@ test_namestore_api_lookup_public_SOURCES = \
204test_namestore_api_lookup_public_LDADD = \ 198test_namestore_api_lookup_public_LDADD = \
205 $(top_builddir)/src/testing/libgnunettesting.la \ 199 $(top_builddir)/src/testing/libgnunettesting.la \
206 $(top_builddir)/src/util/libgnunetutil.la \ 200 $(top_builddir)/src/util/libgnunetutil.la \
201 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
207 $(top_builddir)/src/namestore/libgnunetnamestore.la 202 $(top_builddir)/src/namestore/libgnunetnamestore.la
208 203
209test_namestore_api_put_SOURCES = \ 204test_namestore_api_put_SOURCES = \
@@ -211,6 +206,7 @@ test_namestore_api_put_SOURCES = \
211test_namestore_api_put_LDADD = \ 206test_namestore_api_put_LDADD = \
212 $(top_builddir)/src/testing/libgnunettesting.la \ 207 $(top_builddir)/src/testing/libgnunettesting.la \
213 $(top_builddir)/src/util/libgnunetutil.la \ 208 $(top_builddir)/src/util/libgnunetutil.la \
209 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
214 $(top_builddir)/src/namestore/libgnunetnamestore.la 210 $(top_builddir)/src/namestore/libgnunetnamestore.la
215 211
216test_namestore_api_remove_SOURCES = \ 212test_namestore_api_remove_SOURCES = \
@@ -218,6 +214,7 @@ test_namestore_api_remove_SOURCES = \
218test_namestore_api_remove_LDADD = \ 214test_namestore_api_remove_LDADD = \
219 $(top_builddir)/src/testing/libgnunettesting.la \ 215 $(top_builddir)/src/testing/libgnunettesting.la \
220 $(top_builddir)/src/util/libgnunetutil.la \ 216 $(top_builddir)/src/util/libgnunetutil.la \
217 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
221 $(top_builddir)/src/namestore/libgnunetnamestore.la 218 $(top_builddir)/src/namestore/libgnunetnamestore.la
222 219
223test_namestore_api_remove_not_existing_record_SOURCES = \ 220test_namestore_api_remove_not_existing_record_SOURCES = \
@@ -225,6 +222,7 @@ test_namestore_api_remove_not_existing_record_SOURCES = \
225test_namestore_api_remove_not_existing_record_LDADD = \ 222test_namestore_api_remove_not_existing_record_LDADD = \
226 $(top_builddir)/src/testing/libgnunettesting.la \ 223 $(top_builddir)/src/testing/libgnunettesting.la \
227 $(top_builddir)/src/util/libgnunetutil.la \ 224 $(top_builddir)/src/util/libgnunetutil.la \
225 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
228 $(top_builddir)/src/namestore/libgnunetnamestore.la 226 $(top_builddir)/src/namestore/libgnunetnamestore.la
229 227
230test_namestore_api_zone_to_name_SOURCES = \ 228test_namestore_api_zone_to_name_SOURCES = \
@@ -239,6 +237,7 @@ test_namestore_api_monitoring_SOURCES = \
239test_namestore_api_monitoring_LDADD = \ 237test_namestore_api_monitoring_LDADD = \
240 $(top_builddir)/src/testing/libgnunettesting.la \ 238 $(top_builddir)/src/testing/libgnunettesting.la \
241 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 239 $(top_builddir)/src/namestore/libgnunetnamestore.la \
240 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
242 $(top_builddir)/src/util/libgnunetutil.la 241 $(top_builddir)/src/util/libgnunetutil.la
243 242
244test_namestore_api_monitoring_existing_SOURCES = \ 243test_namestore_api_monitoring_existing_SOURCES = \
@@ -246,6 +245,7 @@ test_namestore_api_monitoring_existing_SOURCES = \
246test_namestore_api_monitoring_existing_LDADD = \ 245test_namestore_api_monitoring_existing_LDADD = \
247 $(top_builddir)/src/testing/libgnunettesting.la \ 246 $(top_builddir)/src/testing/libgnunettesting.la \
248 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 247 $(top_builddir)/src/namestore/libgnunetnamestore.la \
248 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
249 $(top_builddir)/src/util/libgnunetutil.la 249 $(top_builddir)/src/util/libgnunetutil.la
250 250
251test_namestore_api_zone_iteration_SOURCES = \ 251test_namestore_api_zone_iteration_SOURCES = \
@@ -253,6 +253,7 @@ test_namestore_api_zone_iteration_SOURCES = \
253test_namestore_api_zone_iteration_LDADD = \ 253test_namestore_api_zone_iteration_LDADD = \
254 $(top_builddir)/src/testing/libgnunettesting.la \ 254 $(top_builddir)/src/testing/libgnunettesting.la \
255 $(top_builddir)/src/util/libgnunetutil.la \ 255 $(top_builddir)/src/util/libgnunetutil.la \
256 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
256 $(top_builddir)/src/namestore/libgnunetnamestore.la 257 $(top_builddir)/src/namestore/libgnunetnamestore.la
257 258
258test_namestore_api_zone_iteration_specific_zone_SOURCES = \ 259test_namestore_api_zone_iteration_specific_zone_SOURCES = \
@@ -260,6 +261,7 @@ test_namestore_api_zone_iteration_specific_zone_SOURCES = \
260test_namestore_api_zone_iteration_specific_zone_LDADD = \ 261test_namestore_api_zone_iteration_specific_zone_LDADD = \
261 $(top_builddir)/src/testing/libgnunettesting.la \ 262 $(top_builddir)/src/testing/libgnunettesting.la \
262 $(top_builddir)/src/util/libgnunetutil.la \ 263 $(top_builddir)/src/util/libgnunetutil.la \
264 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
263 $(top_builddir)/src/namestore/libgnunetnamestore.la 265 $(top_builddir)/src/namestore/libgnunetnamestore.la
264 266
265test_namestore_api_zone_iteration_stop_SOURCES = \ 267test_namestore_api_zone_iteration_stop_SOURCES = \
@@ -267,13 +269,7 @@ test_namestore_api_zone_iteration_stop_SOURCES = \
267test_namestore_api_zone_iteration_stop_LDADD = \ 269test_namestore_api_zone_iteration_stop_LDADD = \
268 $(top_builddir)/src/testing/libgnunettesting.la \ 270 $(top_builddir)/src/testing/libgnunettesting.la \
269 $(top_builddir)/src/util/libgnunetutil.la \ 271 $(top_builddir)/src/util/libgnunetutil.la \
270 $(top_builddir)/src/namestore/libgnunetnamestore.la 272 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
271
272test_namestore_record_serialization_SOURCES = \
273 test_namestore_record_serialization.c
274test_namestore_record_serialization_LDADD = \
275 $(top_builddir)/src/testing/libgnunettesting.la \
276 $(top_builddir)/src/util/libgnunetutil.la \
277 $(top_builddir)/src/namestore/libgnunetnamestore.la 273 $(top_builddir)/src/namestore/libgnunetnamestore.la
278 274
279test_plugin_namestore_sqlite_SOURCES = \ 275test_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 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file namestore/namestore_api_common.c
23 * @brief API to access the NAMESTORE service
24 * @author Martin Schanzenbach
25 * @author Matthias Wachs
26 * @author Christian Grothoff
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_signatures.h"
32#include "gnunet_arm_service.h"
33#include "gnunet_conversation_service.h"
34#include "gnunet_namestore_service.h"
35#include "gnunet_dnsparser_lib.h"
36#include "gnunet_tun_lib.h"
37#include "namestore.h"
38
39
40#define LOG(kind,...) GNUNET_log_from (kind, "namestore-api",__VA_ARGS__)
41
42GNUNET_NETWORK_STRUCT_BEGIN
43
44
45/**
46 * Internal format of a record in the serialized form.
47 */
48struct NetworkRecord
49{
50
51 /**
52 * Expiration time for the DNS record; relative or absolute depends
53 * on 'flags', network byte order.
54 */
55 uint64_t expiration_time GNUNET_PACKED;
56
57 /**
58 * Number of bytes in 'data', network byte order.
59 */
60 uint32_t data_size GNUNET_PACKED;
61
62 /**
63 * Type of the GNS/DNS record, network byte order.
64 */
65 uint32_t record_type GNUNET_PACKED;
66
67 /**
68 * Flags for the record, network byte order.
69 */
70 uint32_t flags GNUNET_PACKED;
71
72};
73
74GNUNET_NETWORK_STRUCT_END
75
76/**
77 * Convert a UTF-8 string to UTF-8 lowercase
78 * @param src source string
79 * @return converted result
80 */
81char *
82GNUNET_NAMESTORE_normalize_string (const char *src)
83{
84 GNUNET_assert (NULL != src);
85 char *res = strdup (src);
86 /* normalize */
87 GNUNET_STRINGS_utf8_tolower(src, &res);
88 return res;
89}
90
91
92/**
93 * Convert a zone key to a string (for printing debug messages).
94 * This is one of the very few calls in the entire API that is
95 * NOT reentrant!
96 *
97 * @param z the zone key
98 * @return string form; will be overwritten by next call to #GNUNET_NAMESTORE_z2s
99 */
100const char *
101GNUNET_NAMESTORE_z2s (const struct GNUNET_CRYPTO_EcdsaPublicKey *z)
102{
103 static char buf[sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) * 8];
104 char *end;
105
106 end = GNUNET_STRINGS_data_to_string ((const unsigned char *) z,
107 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
108 buf, sizeof (buf));
109 if (NULL == end)
110 {
111 GNUNET_break (0);
112 return NULL;
113 }
114 *end = '\0';
115 return buf;
116}
117
118
119/**
120 * Calculate how many bytes we will need to serialize the given
121 * records.
122 *
123 * @param rd_count number of records in the rd array
124 * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
125 * @return the required size to serialize
126 */
127size_t
128GNUNET_NAMESTORE_records_get_size (unsigned int rd_count,
129 const struct GNUNET_NAMESTORE_RecordData *rd)
130{
131 unsigned int i;
132 size_t ret;
133
134 ret = sizeof (struct NetworkRecord) * rd_count;
135 for (i=0;i<rd_count;i++)
136 {
137 GNUNET_assert ((ret + rd[i].data_size) >= ret);
138 ret += rd[i].data_size;
139 }
140 return ret;
141}
142
143
144/**
145 * Serialize the given records to the given destination buffer.
146 *
147 * @param rd_count number of records in the rd array
148 * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
149 * @param dest_size size of the destination array
150 * @param dest where to write the result
151 * @return the size of serialized records, -1 if records do not fit
152 */
153ssize_t
154GNUNET_NAMESTORE_records_serialize (unsigned int rd_count,
155 const struct GNUNET_NAMESTORE_RecordData *rd,
156 size_t dest_size,
157 char *dest)
158{
159 struct NetworkRecord rec;
160 unsigned int i;
161 size_t off;
162
163 off = 0;
164 for (i=0;i<rd_count;i++)
165 {
166 LOG (GNUNET_ERROR_TYPE_DEBUG,
167 "Serializing record %u with flags %d and expiration time %llu\n",
168 i,
169 rd[i].flags,
170 (unsigned long long) rd[i].expiration_time);
171 rec.expiration_time = GNUNET_htonll (rd[i].expiration_time);
172 rec.data_size = htonl ((uint32_t) rd[i].data_size);
173 rec.record_type = htonl (rd[i].record_type);
174 rec.flags = htonl (rd[i].flags);
175 if (off + sizeof (rec) > dest_size)
176 return -1;
177 memcpy (&dest[off], &rec, sizeof (rec));
178 off += sizeof (rec);
179 if (off + rd[i].data_size > dest_size)
180 return -1;
181 memcpy (&dest[off], rd[i].data, rd[i].data_size);
182 off += rd[i].data_size;
183 }
184 return off;
185}
186
187
188/**
189 * Compares if two records are equal (ignoring flags such
190 * as authority, private and pending, but not relative vs.
191 * absolute expiration time).
192 *
193 * @param a record
194 * @param b record
195 * @return #GNUNET_YES if the records are equal or #GNUNET_NO if they are not
196 */
197int
198GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a,
199 const struct GNUNET_NAMESTORE_RecordData *b)
200{
201 LOG (GNUNET_ERROR_TYPE_DEBUG,
202 "Comparing records\n");
203 if (a->record_type != b->record_type)
204 {
205 LOG (GNUNET_ERROR_TYPE_DEBUG,
206 "Record type %lu != %lu\n", a->record_type, b->record_type);
207 return GNUNET_NO;
208 }
209 if ((a->expiration_time != b->expiration_time) &&
210 ((a->expiration_time != 0) && (b->expiration_time != 0)))
211 {
212 LOG (GNUNET_ERROR_TYPE_DEBUG,
213 "Expiration time %llu != %llu\n",
214 a->expiration_time,
215 b->expiration_time);
216 return GNUNET_NO;
217 }
218 if ((a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS)
219 != (b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS))
220 {
221 LOG (GNUNET_ERROR_TYPE_DEBUG,
222 "Flags %lu (%lu) != %lu (%lu)\n", a->flags,
223 a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS, b->flags,
224 b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS);
225 return GNUNET_NO;
226 }
227 if (a->data_size != b->data_size)
228 {
229 LOG (GNUNET_ERROR_TYPE_DEBUG,
230 "Data size %lu != %lu\n",
231 a->data_size,
232 b->data_size);
233 return GNUNET_NO;
234 }
235 if (0 != memcmp (a->data, b->data, a->data_size))
236 {
237 LOG (GNUNET_ERROR_TYPE_DEBUG,
238 "Data contents do not match\n");
239 return GNUNET_NO;
240 }
241 LOG (GNUNET_ERROR_TYPE_DEBUG,
242 "Records are equal\n");
243 return GNUNET_YES;
244}
245
246
247/**
248 * Deserialize the given records to the given destination.
249 *
250 * @param len size of the serialized record data
251 * @param src the serialized record data
252 * @param rd_count number of records in the rd array
253 * @param dest where to put the data
254 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
255 */
256int
257GNUNET_NAMESTORE_records_deserialize (size_t len,
258 const char *src,
259 unsigned int rd_count,
260 struct GNUNET_NAMESTORE_RecordData *dest)
261{
262 struct NetworkRecord rec;
263 unsigned int i;
264 size_t off;
265
266 off = 0;
267 for (i=0;i<rd_count;i++)
268 {
269 if (off + sizeof (rec) > len)
270 return GNUNET_SYSERR;
271 memcpy (&rec, &src[off], sizeof (rec));
272 dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time);
273 dest[i].data_size = ntohl ((uint32_t) rec.data_size);
274 dest[i].record_type = ntohl (rec.record_type);
275 dest[i].flags = ntohl (rec.flags);
276 off += sizeof (rec);
277 if (off + dest[i].data_size > len)
278 return GNUNET_SYSERR;
279 dest[i].data = &src[off];
280 off += dest[i].data_size;
281 LOG (GNUNET_ERROR_TYPE_DEBUG,
282 "Deserialized record %u with flags %d and expiration time %llu\n",
283 i,
284 dest[i].flags,
285 (unsigned long long) dest[i].expiration_time);
286 }
287 return GNUNET_OK;
288}
289
290
291/**
292 * Returns the expiration time of the given block of records. The block
293 * expiration time is the expiration time of the record with smallest
294 * expiration time.
295 *
296 * @param rd_count number of records given in @a rd
297 * @param rd array of records
298 * @return absolute expiration time
299 */
300struct GNUNET_TIME_Absolute
301GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count,
302 const struct GNUNET_NAMESTORE_RecordData *rd)
303{
304 unsigned int c;
305 struct GNUNET_TIME_Absolute expire;
306 struct GNUNET_TIME_Absolute at;
307 struct GNUNET_TIME_Relative rt;
308
309 if (NULL == rd)
310 return GNUNET_TIME_UNIT_ZERO_ABS;
311 expire = GNUNET_TIME_UNIT_FOREVER_ABS;
312 for (c = 0; c < rd_count; c++)
313 {
314 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
315 {
316 rt.rel_value_us = rd[c].expiration_time;
317 at = GNUNET_TIME_relative_to_absolute (rt);
318 }
319 else
320 {
321 at.abs_value_us = rd[c].expiration_time;
322 }
323 expire = GNUNET_TIME_absolute_min (at, expire);
324 }
325 LOG (GNUNET_ERROR_TYPE_DEBUG,
326 "Determined expiration time for block with %u records to be %s\n",
327 rd_count,
328 GNUNET_STRINGS_absolute_time_to_string (expire));
329 return expire;
330}
331
332
333/**
334 * Derive session key and iv from label and public key.
335 *
336 * @param iv initialization vector to initialize
337 * @param skey session key to initialize
338 * @param label label to use for KDF
339 * @param pub public key to use for KDF
340 */
341static void
342derive_block_aes_key (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
343 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
344 const char *label,
345 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
346{
347 static const char ctx_key[] = "gns-aes-ctx-key";
348 static const char ctx_iv[] = "gns-aes-ctx-iv";
349
350 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
351 pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
352 label, strlen (label),
353 ctx_key, strlen (ctx_key),
354 NULL, 0);
355 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
356 pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
357 label, strlen (label),
358 ctx_iv, strlen (ctx_iv),
359 NULL, 0);
360}
361
362
363/**
364 * Sign name and records
365 *
366 * @param key the private key
367 * @param expire block expiration
368 * @param label the name for the records
369 * @param rd record data
370 * @param rd_count number of records
371 * @return NULL on error (block too large)
372 */
373struct GNUNET_NAMESTORE_Block *
374GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
375 struct GNUNET_TIME_Absolute expire,
376 const char *label,
377 const struct GNUNET_NAMESTORE_RecordData *rd,
378 unsigned int rd_count)
379{
380 size_t payload_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
381 char payload[sizeof (uint32_t) + payload_len];
382 struct GNUNET_NAMESTORE_Block *block;
383 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
384 struct GNUNET_CRYPTO_EcdsaPrivateKey *dkey;
385 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
386 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
387 uint32_t rd_count_nbo;
388
389 if (payload_len > GNUNET_NAMESTORE_MAX_VALUE_SIZE)
390 return NULL;
391 rd_count_nbo = htonl (rd_count);
392 memcpy (payload, &rd_count_nbo, sizeof (uint32_t));
393 GNUNET_assert (payload_len ==
394 GNUNET_NAMESTORE_records_serialize (rd_count, rd,
395 payload_len, &payload[sizeof (uint32_t)]));
396 block = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Block) +
397 sizeof (uint32_t) + payload_len);
398 block->purpose.size = htonl (sizeof (uint32_t) + payload_len +
399 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
400 sizeof (struct GNUNET_TIME_AbsoluteNBO));
401 block->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
402 block->expiration_time = GNUNET_TIME_absolute_hton (expire);
403 dkey = GNUNET_CRYPTO_ecdsa_private_key_derive (key,
404 label,
405 "gns");
406 GNUNET_CRYPTO_ecdsa_key_get_public (dkey,
407 &block->derived_key);
408 GNUNET_CRYPTO_ecdsa_key_get_public (key,
409 &pkey);
410 derive_block_aes_key (&iv, &skey, label, &pkey);
411 GNUNET_break (payload_len + sizeof (uint32_t) ==
412 GNUNET_CRYPTO_symmetric_encrypt (payload, payload_len + sizeof (uint32_t),
413 &skey, &iv,
414 &block[1]));
415 if (GNUNET_OK !=
416 GNUNET_CRYPTO_ecdsa_sign (dkey,
417 &block->purpose,
418 &block->signature))
419 {
420 GNUNET_break (0);
421 GNUNET_free (dkey);
422 GNUNET_free (block);
423 return NULL;
424 }
425 GNUNET_free (dkey);
426 return block;
427}
428
429
430/**
431 * Check if a signature is valid. This API is used by the GNS Block
432 * to validate signatures received from the network.
433 *
434 * @param block block to verify
435 * @return #GNUNET_OK if the signature is valid
436 */
437int
438GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block)
439{
440 return GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN,
441 &block->purpose,
442 &block->signature,
443 &block->derived_key);
444}
445
446
447/**
448 * Decrypt block.
449 *
450 * @param block block to decrypt
451 * @param zone_key public key of the zone
452 * @param label the name for the records
453 * @param proc function to call with the result
454 * @param proc_cls closure for proc
455 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was
456 * not well-formed
457 */
458int
459GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block,
460 const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key,
461 const char *label,
462 GNUNET_NAMESTORE_RecordCallback proc,
463 void *proc_cls)
464{
465 size_t payload_len = ntohl (block->purpose.size) -
466 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) -
467 sizeof (struct GNUNET_TIME_AbsoluteNBO);
468 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
469 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
470
471 if (ntohl (block->purpose.size) <
472 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
473 sizeof (struct GNUNET_TIME_AbsoluteNBO))
474 {
475 GNUNET_break_op (0);
476 return GNUNET_SYSERR;
477 }
478 derive_block_aes_key (&iv, &skey, label, zone_key);
479 {
480 char payload[payload_len];
481 uint32_t rd_count;
482
483 GNUNET_break (payload_len ==
484 GNUNET_CRYPTO_symmetric_decrypt (&block[1], payload_len,
485 &skey, &iv,
486 payload));
487 memcpy (&rd_count,
488 payload,
489 sizeof (uint32_t));
490 rd_count = ntohl (rd_count);
491 if (rd_count > 2048)
492 {
493 /* limit to sane value */
494 GNUNET_break_op (0);
495 return GNUNET_SYSERR;
496 }
497 {
498 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
499
500 if (GNUNET_OK !=
501 GNUNET_NAMESTORE_records_deserialize (payload_len - sizeof (uint32_t),
502 &payload[sizeof (uint32_t)],
503 rd_count,
504 rd))
505 {
506 GNUNET_break_op (0);
507 return GNUNET_SYSERR;
508 }
509 if (NULL != proc)
510 proc (proc_cls, rd_count, (0 != rd_count) ? rd : NULL);
511 }
512 }
513 return GNUNET_OK;
514}
515
516
517/**
518 * Test if a given record is expired.
519 *
520 * @return #GNUNET_YES if the record is expired,
521 * #GNUNET_NO if not
522 */
523int
524GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd)
525{
526 struct GNUNET_TIME_Absolute at;
527
528 if (0 != (rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
529 return GNUNET_NO;
530 at.abs_value_us = rd->expiration_time;
531 return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value_us) ? GNUNET_YES : GNUNET_NO;
532}
533
534
535/**
536 * Calculate the DHT query for a given @a label in a given @a zone.
537 *
538 * @param zone private key of the zone
539 * @param label label of the record
540 * @param query hash to use for the query
541 */
542void
543GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
544 const char *label,
545 struct GNUNET_HashCode *query)
546{
547 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
548
549 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &pub);
550 GNUNET_NAMESTORE_query_from_public_key (&pub, label, query);
551}
552
553
554/**
555 * Calculate the DHT query for a given @a label in a given @a zone.
556 *
557 * @param pub public key of the zone
558 * @param label label of the record
559 * @param query hash to use for the query
560 */
561void
562GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
563 const char *label,
564 struct GNUNET_HashCode *query)
565{
566 struct GNUNET_CRYPTO_EcdsaPublicKey pd;
567
568 GNUNET_CRYPTO_ecdsa_public_key_derive (pub, label, "gns", &pd);
569 GNUNET_CRYPTO_hash (&pd, sizeof (pd), query);
570}
571
572
573/**
574 * Convert public key to the respective absolute domain name in the
575 * ".zkey" pTLD.
576 * This is one of the very few calls in the entire API that is
577 * NOT reentrant!
578 *
579 * @param pkey a public key with a point on the eliptic curve
580 * @return string "X.zkey" where X is the public
581 * key in an encoding suitable for DNS labels.
582 */
583const char *
584GNUNET_NAMESTORE_pkey_to_zkey (const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey)
585{
586 static char ret[128];
587 char *pkeys;
588
589 pkeys = GNUNET_CRYPTO_ecdsa_public_key_to_string (pkey);
590 GNUNET_snprintf (ret,
591 sizeof (ret),
592 "%s.zkey",
593 pkeys);
594 GNUNET_free (pkeys);
595 return ret;
596}
597
598
599/**
600 * Convert an absolute domain name in the ".zkey" pTLD to the
601 * respective public key.
602 *
603 * @param zkey string "X.zkey" where X is the coordinates of the public
604 * key in an encoding suitable for DNS labels.
605 * @param pkey set to a public key on the eliptic curve
606 * @return #GNUNET_SYSERR if @a zkey has the wrong syntax
607 */
608int
609GNUNET_NAMESTORE_zkey_to_pkey (const char *zkey,
610 struct GNUNET_CRYPTO_EcdsaPublicKey *pkey)
611{
612 char *cpy;
613 char *dot;
614 const char *x;
615
616 cpy = GNUNET_strdup (zkey);
617 x = cpy;
618 if (NULL == (dot = strchr (x, (int) '.')))
619 goto error;
620 *dot = '\0';
621 if (0 != strcasecmp (dot + 1,
622 "zkey"))
623 goto error;
624
625 if (GNUNET_OK !=
626 GNUNET_CRYPTO_ecdsa_public_key_from_string (x,
627 strlen (x),
628 pkey))
629 goto error;
630 GNUNET_free (cpy);
631 return GNUNET_OK;
632 error:
633 GNUNET_free (cpy);
634 return GNUNET_SYSERR;
635}
636
637
638/* end of namestore_common.c */