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