GNUnet 0.21.1
gnsrecord_misc.c
Go to the documentation of this file.
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
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"
34
35
36#define LOG(kind, ...) GNUNET_log_from (kind, "gnsrecord", __VA_ARGS__)
37
38char *
40{
41 /*FIXME: We may want to follow RFC5890/RFC5891 */
43}
44
45
47GNUNET_GNSRECORD_label_check (const char*label, char **emsg)
48{
49 if (NULL == label)
50 {
51 *emsg = GNUNET_strdup (_ ("Label is NULL which is not allowed\n"));
52 return GNUNET_NO;
53 }
54 if (0 != strchr (label, '.'))
55 {
56 *emsg = GNUNET_strdup (_ ("Label contains `.' which is not allowed\n"));
57 return GNUNET_NO;
58 }
59 return GNUNET_OK;
60}
61
62
63const char *
65{
66 static char buf[sizeof(struct GNUNET_CRYPTO_PublicKey) * 8];
67 char *end;
68
69 end = GNUNET_STRINGS_data_to_string ((const unsigned char *) z,
70 sizeof(struct
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
94 const struct GNUNET_GNSRECORD_Data *b)
95{
97 "Comparing records\n");
98 if (a->record_type != b->record_type)
99 {
101 "Record type %u != %u\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 {
108 "Expiration time %llu != %llu\n",
109 (unsigned long long) a->expiration_time,
110 (unsigned long long) b->expiration_time);
111 return GNUNET_NO;
112 }
115 {
117 "Flags %u (%u) != %u (%u)\n", a->flags,
120 return GNUNET_NO;
121 }
122 if (a->data_size != b->data_size)
123 {
125 "Data size %llu != %llu\n",
126 (unsigned long long) a->data_size,
127 (unsigned long long) b->data_size);
128 return GNUNET_NO;
129 }
130 if (0 != memcmp (a->data, b->data, a->data_size))
131 {
133 "Data contents do not match\n");
134 return GNUNET_NO;
135 }
137 "Records are equal\n");
138 return GNUNET_YES;
139}
140
141
144 const struct
147{
149 struct GNUNET_TIME_Absolute at;
150 struct GNUNET_TIME_Relative rt;
151 struct GNUNET_TIME_Absolute at_shadow;
152 struct GNUNET_TIME_Relative rt_shadow;
153
154 if (0 == rd_count)
157 for (unsigned int c = 0; c < rd_count; c++)
158 {
159 if (0 != (rd[c].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
160 {
163 }
164 else
165 {
167 }
168
169 for (unsigned int c2 = 0; c2 < rd_count; c2++)
170 {
171 /* Check for shadow record */
172 if ((c == c2) ||
173 (rd[c].record_type != rd[c2].record_type) ||
174 (0 == (rd[c2].flags & GNUNET_GNSRECORD_RF_SHADOW)))
175 continue;
176 /* We have a shadow record */
177 if (0 != (rd[c2].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
178 {
179 rt_shadow.rel_value_us = rd[c2].expiration_time;
180 at_shadow = GNUNET_TIME_relative_to_absolute (rt_shadow);
181 }
182 else
183 {
184 at_shadow.abs_value_us = rd[c2].expiration_time;
185 }
187 at_shadow);
188 }
190 expire);
191 }
194 "Determined expiration time for block with %u records to be %s\n",
195 rd_count,
197 return expire;
198}
199
200
207int
209{
210 struct GNUNET_TIME_Absolute at;
211
213 return GNUNET_NO;
215 return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value_us) ?
217}
218
219
230const char *
232{
233 static char ret[128];
234 char *pkeys;
235
238 sizeof(ret),
239 "%s",
240 pkeys);
241 GNUNET_free (pkeys);
242 return ret;
243}
244
245
255int
258{
259 if (GNUNET_OK !=
261 pkey))
262 return GNUNET_SYSERR;
263 return GNUNET_OK;
264}
265
266
269 size_t data_size,
270 uint32_t type,
272{
274 return GNUNET_SYSERR;
275 switch (type)
276 {
278 if (data_size > sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))
279 return GNUNET_SYSERR;
280 memcpy (&key->ecdsa_key, data, data_size);
281 break;
283 if (data_size > sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))
284 return GNUNET_SYSERR;
285 memcpy (&key->eddsa_key, data, data_size);
286 break;
287 default:
288 return GNUNET_NO;
289 }
290 key->type = htonl (type);
291
292 return GNUNET_YES;
293}
294
295
299 char **data,
300 size_t *data_size,
301 uint32_t *type)
302{
303 char *tmp;
304 *type = ntohl (key->type);
306 if (0 == *data_size)
307 return GNUNET_SYSERR;
308 tmp = GNUNET_malloc (*data_size);
309 memcpy (tmp, ((char*) key) + sizeof (key->type), *data_size);
310 *data = tmp;
311 return GNUNET_OK;
312}
313
314
317{
318 switch (type)
319 {
322 return GNUNET_YES;
323 default:
324 return GNUNET_NO;
325 }
326}
327
328
329size_t
331{
332 return ntohl (block->size);
333}
334
335
339{
340
341 switch (ntohl (block->type))
342 {
344 return GNUNET_TIME_absolute_ntoh (block->ecdsa_block.expiration_time);
346 return GNUNET_TIME_absolute_ntoh (block->eddsa_block.expiration_time);
347 default:
348 GNUNET_break (0); /* Hopefully we never get here, but we might */
349 }
351
352}
353
354
357 struct GNUNET_HashCode *query)
358{
359 switch (ntohl (block->type))
360 {
363 sizeof (block->ecdsa_block.derived_key),
364 query);
365 return GNUNET_OK;
368 sizeof (block->eddsa_block.derived_key),
369 query);
370 return GNUNET_OK;
371 default:
372 return GNUNET_SYSERR;
373 }
374 return GNUNET_SYSERR;
375
376}
377
378
382{
384 "Got record of type %u\n",
385 rd->record_type);
386 switch (rd->record_type)
387 {
389 key->type = htonl (rd->record_type);
390 memcpy (&key->ecdsa_key, rd->data, sizeof (key->ecdsa_key));
391 return GNUNET_OK;
393 key->type = htonl (rd->record_type);
394 memcpy (&key->eddsa_key, rd->data, sizeof (key->eddsa_key));
395 return GNUNET_OK;
396 default:
397 return GNUNET_SYSERR;
398 }
399 return GNUNET_SYSERR;
400
401
402}
403
404
407 const struct
409 unsigned int rd_count,
410 struct GNUNET_GNSRECORD_Data *
411 rd_public,
412 unsigned int *rd_count_public,
413 struct GNUNET_TIME_Absolute *expiry,
415 char **emsg)
416{
417 struct GNUNET_TIME_Absolute now;
418 struct GNUNET_TIME_Absolute minimum_expiration;
419 int have_zone_delegation = GNUNET_NO;
420 int have_gns2dns = GNUNET_NO;
421 int have_other = GNUNET_NO;
422 int have_redirect = GNUNET_NO;
423 int have_empty_label = (0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, label));
424 unsigned int rd_count_tmp;
425
426 minimum_expiration = GNUNET_TIME_UNIT_ZERO_ABS;
428 rd_count_tmp = 0;
429 for (unsigned int i = 0; i < rd_count; i++)
430 {
431 /* Ignore private records for public record set */
433 (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)))
434 {
436 "Filtering private record filter=%u...\n", filter);
437 continue;
438 }
439 /* Skip expired records */
440 if ((0 == (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) &&
441 (rd[i].expiration_time < now.abs_value_us))
442 {
444 "Filtering expired record...\n");
445 continue; /* record already expired, skip it */
446 }
447 /* Ignore the maintenance record (e.g. tombstone) unless filter permits explicitly.
448 * Remember expiration time. */
449 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_MAINTENANCE))
450 {
452 {
453 rd_public[rd_count_tmp] = rd[i];
454 rd_count_tmp++;
455 }
456 continue;
457 }
458 /* No NICK records unless empty label */
459 if (have_empty_label &&
460 (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type))
461 continue;
462
472 if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type))
473 {
474 /* No delegation records under empty label*/
475 if (have_empty_label)
476 {
477 *emsg = GNUNET_strdup (_ (
478 "Zone delegation record not allowed in apex."));
479 return GNUNET_SYSERR;
480 }
481 if ((GNUNET_YES == have_other) ||
482 (GNUNET_YES == have_redirect) ||
483 (GNUNET_YES == have_gns2dns))
484 {
485 *emsg = GNUNET_strdup (_ (
486 "Zone delegation record set contains mutually exclusive records."));
487 return GNUNET_SYSERR;
488 }
489 have_zone_delegation = GNUNET_YES;
490 }
491 else if (GNUNET_GNSRECORD_TYPE_REDIRECT == rd[i].record_type)
492 {
493 if (GNUNET_YES == have_redirect)
494 {
495 *emsg = GNUNET_strdup (_ (
496 "Multiple REDIRECT records."));
497 return GNUNET_SYSERR;
498
499 }
500 if ((GNUNET_YES == have_other) ||
501 (GNUNET_YES == have_zone_delegation) ||
502 (GNUNET_YES == have_gns2dns))
503 {
504 *emsg = GNUNET_strdup (_ (
505 "Redirection record set contains mutually exclusive records."));
506 return GNUNET_SYSERR;
507 }
508 /* No redirection 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 have_redirect = GNUNET_YES;
516 }
517 else if (GNUNET_GNSRECORD_TYPE_GNS2DNS == rd[i].record_type)
518 {
519 /* No gns2dns records under empty label*/
520 if (have_empty_label)
521 {
522 *emsg = GNUNET_strdup (_ (
523 "Redirection records not allowed in apex.."));
524 return GNUNET_SYSERR;
525 }
526 if ((GNUNET_YES == have_other) ||
527 (GNUNET_YES == have_redirect) ||
528 (GNUNET_YES == have_zone_delegation))
529 {
530 *emsg = GNUNET_strdup (_ (
531 "Redirection record set contains mutually exclusive records."));
532 return GNUNET_SYSERR;
533 }
534 have_gns2dns = GNUNET_YES;
535 }
536 else
537 {
538 /* Some other record.
539 * Not allowed for zone delegations or redirections */
540 if ((GNUNET_YES == have_zone_delegation) ||
541 (GNUNET_YES == have_redirect) ||
542 (GNUNET_YES == have_gns2dns))
543 {
544 *emsg = GNUNET_strdup (_ (
545 "Mutually exclusive records."));
546 return GNUNET_SYSERR;
547 }
548 have_other = GNUNET_YES;
549 }
550
551 rd_public[rd_count_tmp] = rd[i];
552 /* Make sure critical record types are marked as such */
553 if (GNUNET_YES == GNUNET_GNSRECORD_is_critical (rd[i].record_type))
554 rd_public[rd_count_tmp].flags |= GNUNET_GNSRECORD_RF_CRITICAL;
555 rd_count_tmp++;
556 }
557
558 *expiry = GNUNET_GNSRECORD_record_get_expiration_time (rd_count_tmp,
559 rd_public,
560 minimum_expiration);
561 *rd_count_public = rd_count_tmp;
562 return GNUNET_OK;
563}
564
565
566/* end of gnsrecord_misc.c */
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_record_to_identity_key(const struct GNUNET_GNSRECORD_Data *rd, struct GNUNET_CRYPTO_PublicKey *key)
#define LOG(kind,...)
static int ret
Final status code.
Definition: gnunet-arm.c:94
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static char * expire
DID Document expiration Date Attribut String.
Definition: gnunet-did.c:98
static char * pkey
Public key of the zone to look in, in ASCII.
static unsigned int rd_count
Number of records for currently parsed set.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static uint32_t type
Type string converted to DNS type value.
static size_t data_size
Number of bytes in data.
static struct GNUNET_CONTAINER_BloomFilter * filter
Bloomfilter to quickly tell if we don't have the content.
API that can be used to manipulate GNS record data.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_label_check(const char *label, char **emsg)
Check label for invalid characters.
#define GNUNET_GNSRECORD_RF_RCMP_FLAGS
Include the record types generated from GANA.
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_CRYPTO_PublicKey *z)
Convert a zone to a string (for printing debug messages).
int GNUNET_GNSRECORD_zkey_to_pkey(const char *zkey, struct GNUNET_CRYPTO_PublicKey *pkey)
Convert an absolute domain name to the respective public key.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_data_from_identity(const struct GNUNET_CRYPTO_PublicKey *key, char **data, size_t *data_size, uint32_t *type)
Create record data and size from an identity key.
struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_record_get_expiration_time(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, struct GNUNET_TIME_Absolute min)
Returns the expiration time of the given block of records.
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_CRYPTO_PublicKey *pkey)
Convert public key to the respective absolute domain name in the ".zkey" pTLD.
size_t GNUNET_GNSRECORD_block_get_size(const struct GNUNET_GNSRECORD_Block *block)
Returns the length of this block in bytes.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_records_cmp(const struct GNUNET_GNSRECORD_Data *a, const struct GNUNET_GNSRECORD_Data *b)
Compares if two records are equal (ignoring flags such as authority, private and pending,...
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_query_from_block(const struct GNUNET_GNSRECORD_Block *block, struct GNUNET_HashCode *query)
Builds the query hash from a block.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_identity_from_data(const char *data, size_t data_size, uint32_t type, struct GNUNET_CRYPTO_PublicKey *key)
Build a #GNUNET_GNSRECORD_PublicKey from zone delegation resource record data.
int GNUNET_GNSRECORD_is_expired(const struct GNUNET_GNSRECORD_Data *rd)
Test if a given record is expired.
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_is_critical(uint32_t type)
Check if this type is a critical record.
Definition: gnsrecord.c:247
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_is_zonekey_type(uint32_t type)
Check if this type is one of the supported GNS zone types.
char * GNUNET_GNSRECORD_string_normalize(const char *src)
Normalize a UTF-8 string to a GNS name.
GNUNET_GNSRECORD_Filter
Filter for GNUNET_GNSRECORD_normalize_record_set().
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_normalize_record_set(const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *rd_public, unsigned int *rd_count_public, struct GNUNET_TIME_Absolute *expiry, enum GNUNET_GNSRECORD_Filter filter, char **emsg)
Normalize namestore records: Check for consistency and expirations.
struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_block_get_expiration(const struct GNUNET_GNSRECORD_Block *block)
Returns the expiration of a block.
@ GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION
This expiration time of the record is a relative time (not an absolute time).
@ GNUNET_GNSRECORD_RF_CRITICAL
This record is critical.
@ GNUNET_GNSRECORD_RF_MAINTENANCE
Maintenance records.
@ GNUNET_GNSRECORD_RF_SHADOW
This record should not be used unless all (other) records in the set with an absolute expiration time...
@ GNUNET_GNSRECORD_RF_PRIVATE
This is a private record of this peer and it should thus not be published.
@ GNUNET_GNSRECORD_FILTER_INCLUDE_MAINTENANCE
Include maintenance records (TOMBSTONE etc).
@ GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE
Filter private records.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
ssize_t GNUNET_CRYPTO_public_key_get_length(const struct GNUNET_CRYPTO_PublicKey *key)
Get the compacted length of a GNUNET_CRYPTO_PublicKey.
Definition: crypto_pkey.c:68
#define GNUNET_log(kind,...)
char * GNUNET_CRYPTO_public_key_to_string(const struct GNUNET_CRYPTO_PublicKey *key)
Creates a (Base32) string representation of the public key.
Definition: crypto_pkey.c:551
GNUNET_GenericReturnValue
Named constants for return values.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_public_key_from_string(const char *str, struct GNUNET_CRYPTO_PublicKey *key)
Parses a (Base32) string representation of the public key.
Definition: crypto_pkey.c:571
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
char * GNUNET_STRINGS_data_to_string(const void *data, size_t size, char *out, size_t out_size)
Convert binary data to ASCII encoding using CrockfordBase32.
Definition: strings.c:709
char * GNUNET_STRINGS_utf8_normalize(const char *input)
Normalize the utf-8 input string to NFC.
Definition: strings.c:429
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_zero_(void)
Return absolute time of 0ms.
Definition: time.c:142
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:405
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition: time.c:367
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:737
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:316
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_min(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the minimum of two absolute time values.
Definition: time.c:359
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:617
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define min(x, y)
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
#define GNUNET_GNSRECORD_TYPE_NICK
GNS zone nickname.
#define GNUNET_GNSRECORD_TYPE_GNS2DNS
Delegation to DNS.
#define GNUNET_GNSRECORD_TYPE_REDIRECT
Redirection record.
#define GNUNET_GNSRECORD_TYPE_PKEY
WARNING: This header is generated! In order to add GNS record types, you must register them in GANA,...
#define GNUNET_GNSRECORD_TYPE_EDKEY
GNS zone delegation (EDKEY)
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...
An identity key as per LSD0001.
uint32_t type
The zone type (GNUNET_GNSRECORD_TYPE_PKEY)
struct GNUNET_GNSRECORD_EcdsaBlock ecdsa_block
struct GNUNET_GNSRECORD_EddsaBlock eddsa_block
uint32_t size
Size of the block.
uint32_t record_type
Type of the GNS/DNS record.
const void * data
Binary value stored in the DNS record.
size_t data_size
Number of bytes in data.
enum GNUNET_GNSRECORD_Flags flags
Flags for the record.
uint64_t expiration_time
Expiration time for the DNS record.
struct GNUNET_CRYPTO_EcdsaPublicKey derived_key
Derived key used for signing; hash of this is the query.
struct GNUNET_CRYPTO_EddsaPublicKey derived_key
Derived key used for signing; hash of this is the query.
A 512-bit hashcode.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.