aboutsummaryrefslogtreecommitdiff
path: root/src/gnsrecord/gnsrecord_misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gnsrecord/gnsrecord_misc.c')
-rw-r--r--src/gnsrecord/gnsrecord_misc.c584
1 files changed, 0 insertions, 584 deletions
diff --git a/src/gnsrecord/gnsrecord_misc.c b/src/gnsrecord/gnsrecord_misc.c
deleted file mode 100644
index 54d8fb860..000000000
--- a/src/gnsrecord/gnsrecord_misc.c
+++ /dev/null
@@ -1,584 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
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
40char *
41GNUNET_GNSRECORD_string_normalize (const char *src)
42{
43 /*FIXME: We may want to follow RFC5890/RFC5891 */
44 return GNUNET_STRINGS_utf8_normalize (src);
45}
46
47enum GNUNET_GenericReturnValue
48GNUNET_GNSRECORD_label_check (const char*label, char **emsg)
49{
50 if (NULL == label)
51 {
52 *emsg = GNUNET_strdup (_ ("Label is NULL which is not allowed\n"));
53 return GNUNET_NO;
54 }
55 if (0 != strchr (label, '.'))
56 {
57 *emsg = GNUNET_strdup (_ ("Label contains `.' which is not allowed\n"));
58 return GNUNET_NO;
59 }
60 return GNUNET_OK;
61}
62
63/**
64 * Convert a zone key to a string (for printing debug messages).
65 * This is one of the very few calls in the entire API that is
66 * NOT reentrant!
67 *
68 * @param z the zone key
69 * @return string form; will be overwritten by next call to #GNUNET_GNSRECORD_z2s
70 */
71const char *
72GNUNET_GNSRECORD_z2s (const struct GNUNET_IDENTITY_PublicKey *z)
73{
74 static char buf[sizeof(struct GNUNET_IDENTITY_PublicKey) * 8];
75 char *end;
76
77 end = GNUNET_STRINGS_data_to_string ((const unsigned char *) z,
78 sizeof(struct
79 GNUNET_IDENTITY_PublicKey),
80 buf, sizeof(buf));
81 if (NULL == end)
82 {
83 GNUNET_break (0);
84 return NULL;
85 }
86 *end = '\0';
87 return buf;
88}
89
90
91/**
92 * Compares if two records are equal (ignoring flags such
93 * as authority, private and pending, but not relative vs.
94 * absolute expiration time).
95 *
96 * @param a record
97 * @param b record
98 * @return #GNUNET_YES if the records are equal or #GNUNET_NO if they are not
99 */
100int
101GNUNET_GNSRECORD_records_cmp (const struct GNUNET_GNSRECORD_Data *a,
102 const struct GNUNET_GNSRECORD_Data *b)
103{
104 LOG (GNUNET_ERROR_TYPE_DEBUG,
105 "Comparing records\n");
106 if (a->record_type != b->record_type)
107 {
108 LOG (GNUNET_ERROR_TYPE_DEBUG,
109 "Record type %u != %u\n", a->record_type, b->record_type);
110 return GNUNET_NO;
111 }
112 if ((a->expiration_time != b->expiration_time) &&
113 ((a->expiration_time != 0) && (b->expiration_time != 0)))
114 {
115 LOG (GNUNET_ERROR_TYPE_DEBUG,
116 "Expiration time %llu != %llu\n",
117 (unsigned long long) a->expiration_time,
118 (unsigned long long) b->expiration_time);
119 return GNUNET_NO;
120 }
121 if ((a->flags & GNUNET_GNSRECORD_RF_RCMP_FLAGS)
122 != (b->flags & GNUNET_GNSRECORD_RF_RCMP_FLAGS))
123 {
124 LOG (GNUNET_ERROR_TYPE_DEBUG,
125 "Flags %u (%u) != %u (%u)\n", a->flags,
126 a->flags & GNUNET_GNSRECORD_RF_RCMP_FLAGS, b->flags,
127 b->flags & GNUNET_GNSRECORD_RF_RCMP_FLAGS);
128 return GNUNET_NO;
129 }
130 if (a->data_size != b->data_size)
131 {
132 LOG (GNUNET_ERROR_TYPE_DEBUG,
133 "Data size %lu != %lu\n",
134 a->data_size,
135 b->data_size);
136 return GNUNET_NO;
137 }
138 if (0 != memcmp (a->data, b->data, a->data_size))
139 {
140 LOG (GNUNET_ERROR_TYPE_DEBUG,
141 "Data contents do not match\n");
142 return GNUNET_NO;
143 }
144 LOG (GNUNET_ERROR_TYPE_DEBUG,
145 "Records are equal\n");
146 return GNUNET_YES;
147}
148
149
150struct GNUNET_TIME_Absolute
151GNUNET_GNSRECORD_record_get_expiration_time (unsigned int rd_count,
152 const struct
153 GNUNET_GNSRECORD_Data *rd,
154 struct GNUNET_TIME_Absolute min)
155{
156 struct GNUNET_TIME_Absolute expire;
157 struct GNUNET_TIME_Absolute at;
158 struct GNUNET_TIME_Relative rt;
159 struct GNUNET_TIME_Absolute at_shadow;
160 struct GNUNET_TIME_Relative rt_shadow;
161
162 if (0 == rd_count)
163 return GNUNET_TIME_absolute_max (GNUNET_TIME_UNIT_ZERO_ABS, min);
164 expire = GNUNET_TIME_UNIT_FOREVER_ABS;
165 for (unsigned int c = 0; c < rd_count; c++)
166 {
167 if (0 != (rd[c].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
168 {
169 rt.rel_value_us = rd[c].expiration_time;
170 at = GNUNET_TIME_relative_to_absolute (rt);
171 }
172 else
173 {
174 at.abs_value_us = rd[c].expiration_time;
175 }
176
177 for (unsigned int c2 = 0; c2 < rd_count; c2++)
178 {
179 /* Check for shadow record */
180 if ((c == c2) ||
181 (rd[c].record_type != rd[c2].record_type) ||
182 (0 == (rd[c2].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD)))
183 continue;
184 /* We have a shadow record */
185 if (0 != (rd[c2].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
186 {
187 rt_shadow.rel_value_us = rd[c2].expiration_time;
188 at_shadow = GNUNET_TIME_relative_to_absolute (rt_shadow);
189 }
190 else
191 {
192 at_shadow.abs_value_us = rd[c2].expiration_time;
193 }
194 at = GNUNET_TIME_absolute_max (at,
195 at_shadow);
196 }
197 expire = GNUNET_TIME_absolute_min (at,
198 expire);
199 }
200 expire = GNUNET_TIME_absolute_max (expire, min);
201 LOG (GNUNET_ERROR_TYPE_DEBUG,
202 "Determined expiration time for block with %u records to be %s\n",
203 rd_count,
204 GNUNET_STRINGS_absolute_time_to_string (expire));
205 return expire;
206}
207
208
209/**
210 * Test if a given record is expired.
211 *
212 * @return #GNUNET_YES if the record is expired,
213 * #GNUNET_NO if not
214 */
215int
216GNUNET_GNSRECORD_is_expired (const struct GNUNET_GNSRECORD_Data *rd)
217{
218 struct GNUNET_TIME_Absolute at;
219
220 if (0 != (rd->flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
221 return GNUNET_NO;
222 at.abs_value_us = rd->expiration_time;
223 return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value_us) ?
224 GNUNET_YES : GNUNET_NO;
225}
226
227
228/**
229 * Convert public key to the respective absolute domain name in the
230 * ".zkey" pTLD.
231 * This is one of the very few calls in the entire API that is
232 * NOT reentrant!
233 *
234 * @param pkey a public key with a point on the eliptic curve
235 * @return string "X.zkey" where X is the public
236 * key in an encoding suitable for DNS labels.
237 */
238const char *
239GNUNET_GNSRECORD_pkey_to_zkey (const struct GNUNET_IDENTITY_PublicKey *pkey)
240{
241 static char ret[128];
242 char *pkeys;
243
244 pkeys = GNUNET_IDENTITY_public_key_to_string (pkey);
245 GNUNET_snprintf (ret,
246 sizeof(ret),
247 "%s",
248 pkeys);
249 GNUNET_free (pkeys);
250 return ret;
251}
252
253
254/**
255 * Convert an absolute domain name to the
256 * respective public key.
257 *
258 * @param zkey string encoding the coordinates of the public
259 * key in an encoding suitable for DNS labels.
260 * @param pkey set to a public key on the eliptic curve
261 * @return #GNUNET_SYSERR if @a zkey has the wrong syntax
262 */
263int
264GNUNET_GNSRECORD_zkey_to_pkey (const char *zkey,
265 struct GNUNET_IDENTITY_PublicKey *pkey)
266{
267 if (GNUNET_OK !=
268 GNUNET_IDENTITY_public_key_from_string (zkey,
269 pkey))
270 return GNUNET_SYSERR;
271 return GNUNET_OK;
272}
273
274
275enum GNUNET_GenericReturnValue
276GNUNET_GNSRECORD_identity_from_data (const char *data,
277 size_t data_size,
278 uint32_t type,
279 struct GNUNET_IDENTITY_PublicKey *key)
280{
281 if (GNUNET_NO == GNUNET_GNSRECORD_is_zonekey_type (type))
282 return GNUNET_SYSERR;
283 switch (type)
284 {
285 case GNUNET_GNSRECORD_TYPE_PKEY:
286 if (data_size > sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))
287 return GNUNET_SYSERR;
288 memcpy (&key->ecdsa_key, data, data_size);
289 break;
290 case GNUNET_GNSRECORD_TYPE_EDKEY:
291 if (data_size > sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))
292 return GNUNET_SYSERR;
293 memcpy (&key->eddsa_key, data, data_size);
294 break;
295 default:
296 return GNUNET_NO;
297 }
298 key->type = htonl (type);
299
300 return GNUNET_YES;
301}
302
303
304enum GNUNET_GenericReturnValue
305GNUNET_GNSRECORD_data_from_identity (const struct
306 GNUNET_IDENTITY_PublicKey *key,
307 char **data,
308 size_t *data_size,
309 uint32_t *type)
310{
311 char *tmp;
312 *type = ntohl (key->type);
313 *data_size = GNUNET_IDENTITY_key_get_length (key) - sizeof (key->type);
314 if (0 == *data_size)
315 return GNUNET_SYSERR;
316 tmp = GNUNET_malloc (*data_size);
317 memcpy (tmp, ((char*) key) + sizeof (key->type), *data_size);
318 *data = tmp;
319 return GNUNET_OK;
320}
321
322
323enum GNUNET_GenericReturnValue
324GNUNET_GNSRECORD_is_zonekey_type (uint32_t type)
325{
326 switch (type)
327 {
328 case GNUNET_GNSRECORD_TYPE_PKEY:
329 case GNUNET_GNSRECORD_TYPE_EDKEY:
330 return GNUNET_YES;
331 default:
332 return GNUNET_NO;
333 }
334}
335
336
337size_t
338GNUNET_GNSRECORD_block_get_size (const struct GNUNET_GNSRECORD_Block *block)
339{
340 return ntohl (block->size);
341}
342
343
344struct GNUNET_TIME_Absolute
345GNUNET_GNSRECORD_block_get_expiration (const struct
346 GNUNET_GNSRECORD_Block *block)
347{
348
349 switch (ntohl (block->type))
350 {
351 case GNUNET_GNSRECORD_TYPE_PKEY:
352 return GNUNET_TIME_absolute_ntoh (block->ecdsa_block.expiration_time);
353 case GNUNET_GNSRECORD_TYPE_EDKEY:
354 return GNUNET_TIME_absolute_ntoh (block->eddsa_block.expiration_time);
355 default:
356 GNUNET_break (0); /* Hopefully we never get here, but we might */
357 }
358 return GNUNET_TIME_absolute_get_zero_ ();
359
360}
361
362
363enum GNUNET_GenericReturnValue
364GNUNET_GNSRECORD_query_from_block (const struct GNUNET_GNSRECORD_Block *block,
365 struct GNUNET_HashCode *query)
366{
367 switch (ntohl (block->type))
368 {
369 case GNUNET_GNSRECORD_TYPE_PKEY:
370 GNUNET_CRYPTO_hash (&(block->ecdsa_block.derived_key),
371 sizeof (block->ecdsa_block.derived_key),
372 query);
373 return GNUNET_OK;
374 case GNUNET_GNSRECORD_TYPE_EDKEY:
375 GNUNET_CRYPTO_hash (&block->eddsa_block.derived_key,
376 sizeof (block->eddsa_block.derived_key),
377 query);
378 return GNUNET_OK;
379 default:
380 return GNUNET_SYSERR;
381 }
382 return GNUNET_SYSERR;
383
384}
385
386
387enum GNUNET_GenericReturnValue
388GNUNET_GNSRECORD_record_to_identity_key (const struct GNUNET_GNSRECORD_Data *rd,
389 struct GNUNET_IDENTITY_PublicKey *key)
390{
391 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
392 "Got record of type %u\n",
393 rd->record_type);
394 switch (rd->record_type)
395 {
396 case GNUNET_GNSRECORD_TYPE_PKEY:
397 key->type = htonl (rd->record_type);
398 memcpy (&key->ecdsa_key, rd->data, sizeof (key->ecdsa_key));
399 return GNUNET_OK;
400 case GNUNET_GNSRECORD_TYPE_EDKEY:
401 key->type = htonl (rd->record_type);
402 memcpy (&key->eddsa_key, rd->data, sizeof (key->eddsa_key));
403 return GNUNET_OK;
404 default:
405 return GNUNET_SYSERR;
406 }
407 return GNUNET_SYSERR;
408
409
410}
411
412enum GNUNET_GenericReturnValue
413GNUNET_GNSRECORD_normalize_record_set (const char *label,
414 const struct
415 GNUNET_GNSRECORD_Data *rd,
416 unsigned int rd_count,
417 struct GNUNET_GNSRECORD_Data *
418 rd_public,
419 unsigned int *rd_count_public,
420 struct GNUNET_TIME_Absolute *expiry,
421 int include_private,
422 char **emsg)
423{
424 struct GNUNET_TIME_Absolute now;
425 struct GNUNET_TIME_Absolute minimum_expiration;
426 int have_zone_delegation = GNUNET_NO;
427 int have_gns2dns = GNUNET_NO;
428 int have_other = GNUNET_NO;
429 int have_redirect = GNUNET_NO;
430 int have_empty_label = (0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, label));
431 unsigned int rd_count_tmp;
432
433 minimum_expiration = GNUNET_TIME_UNIT_ZERO_ABS;
434 now = GNUNET_TIME_absolute_get ();
435 rd_count_tmp = 0;
436 for (unsigned int i = 0; i < rd_count; i++)
437 {
438 /* Ignore the tombstone. For maintenance only. Remember expiration time. */
439 if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type)
440 {
441 minimum_expiration.abs_value_us = rd[i].expiration_time;
442 continue;
443 }
444 /* No NICK records unless empty label */
445 if (have_empty_label &&
446 (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type))
447 continue;
448
449 /**
450 * Check for delegation and redirect consistency.
451 * Note that we check for consistency BEFORE we filter for
452 * private records ON PURPOSE.
453 * We also want consistent record sets in our local zone(s).
454 * The only exception is the tombstone (above) which we ignore
455 * for the consistency check(s).
456 * FIXME: What about shadow records? Should we ignore them?
457 */
458 if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type))
459 {
460 /* No delegation records under empty label*/
461 if (have_empty_label)
462 {
463 *emsg = GNUNET_strdup (_ (
464 "Zone delegation record not allowed in apex."));
465 return GNUNET_SYSERR;
466 }
467 if ((GNUNET_YES == have_other) ||
468 (GNUNET_YES == have_redirect) ||
469 (GNUNET_YES == have_gns2dns))
470 {
471 *emsg = GNUNET_strdup (_ (
472 "Zone delegation record set contains mutually exclusive records."));
473 return GNUNET_SYSERR;
474 }
475 have_zone_delegation = GNUNET_YES;
476 }
477 else if (GNUNET_GNSRECORD_TYPE_REDIRECT == rd[i].record_type)
478 {
479 if (GNUNET_YES == have_redirect)
480 {
481 *emsg = GNUNET_strdup (_ (
482 "Multiple REDIRECT records."));
483 return GNUNET_SYSERR;
484
485 }
486 if ((GNUNET_YES == have_other) ||
487 (GNUNET_YES == have_zone_delegation) ||
488 (GNUNET_YES == have_gns2dns))
489 {
490 *emsg = GNUNET_strdup (_ (
491 "Redirection record set conains mutually exclusive records."));
492 return GNUNET_SYSERR;
493 }
494 /* No redirection records under empty label*/
495 if (have_empty_label)
496 {
497 *emsg = GNUNET_strdup (_ (
498 "Redirection records not allowed in apex."));
499 return GNUNET_SYSERR;
500 }
501 have_redirect = GNUNET_YES;
502 }
503 else if (GNUNET_GNSRECORD_TYPE_GNS2DNS == rd[i].record_type)
504 {
505 /* No gns2dns records under empty label*/
506 if (have_empty_label)
507 {
508 *emsg = GNUNET_strdup (_ (
509 "Redirection records not allowed in apex.."));
510 return GNUNET_SYSERR;
511 }
512 if ((GNUNET_YES == have_other) ||
513 (GNUNET_YES == have_redirect) ||
514 (GNUNET_YES == have_zone_delegation))
515 {
516 *emsg = GNUNET_strdup (_ (
517 "Redirection record set conains mutually exclusive records."));
518 return GNUNET_SYSERR;
519 }
520 have_gns2dns = GNUNET_YES;
521 }
522 else
523 {
524 /* Some other record.
525 * Not allowed for zone delegations or redirections */
526 if ((GNUNET_YES == have_zone_delegation) ||
527 (GNUNET_YES == have_redirect) ||
528 (GNUNET_YES == have_gns2dns))
529 {
530 *emsg = GNUNET_strdup (_ (
531 "Mutually exclusive records."));
532 return GNUNET_SYSERR;
533 }
534 have_other = GNUNET_YES;
535 }
536
537 /* Ignore private records for public record set */
538
539 if ((GNUNET_NO == include_private) &&
540 (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)))
541 continue;
542 /* Skip expired records */
543 if ((0 == (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) &&
544 (rd[i].expiration_time < now.abs_value_us))
545 continue; /* record already expired, skip it */
546 rd_public[rd_count_tmp] = rd[i];
547 /* Make sure critical record types are marked as such */
548 if (GNUNET_YES == GNUNET_GNSRECORD_is_critical (rd[i].record_type))
549 rd_public[rd_count_tmp].flags |= GNUNET_GNSRECORD_RF_CRITICAL;
550 rd_count_tmp++;
551 }
552
553 *expiry = GNUNET_GNSRECORD_record_get_expiration_time (rd_count_tmp,
554 rd_public,
555 minimum_expiration);
556 *rd_count_public = rd_count_tmp;
557 return GNUNET_OK;
558}
559
560enum GNUNET_GenericReturnValue
561GNUNET_GNSRECORD_convert_records_for_export (const char *label,
562 const struct
563 GNUNET_GNSRECORD_Data *rd,
564 unsigned int rd_count,
565 struct GNUNET_GNSRECORD_Data *
566 rd_public,
567 unsigned int *rd_count_public,
568 struct GNUNET_TIME_Absolute *expiry,
569 char **emsg)
570{
571 return GNUNET_GNSRECORD_normalize_record_set (label,
572 rd,
573 rd_count,
574 rd_public,
575 rd_count_public,
576 expiry,
577 GNUNET_NO,
578 emsg);
579
580}
581
582
583
584/* end of gnsrecord_misc.c */