GNUnet 0.22.2
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"
31
32
33#define LOG(kind, ...) GNUNET_log_from (kind, "gnsrecord", __VA_ARGS__)
34
35char *
37{
38 /*FIXME: We may want to follow RFC5890/RFC5891 */
40}
41
42
44GNUNET_GNSRECORD_label_check (const char*label, char **emsg)
45{
46 if (NULL == label)
47 {
48 *emsg = GNUNET_strdup (_ ("Label is NULL which is not allowed\n"));
49 return GNUNET_NO;
50 }
51 if (0 != strchr (label, '.'))
52 {
53 *emsg = GNUNET_strdup (_ ("Label contains `.' which is not allowed\n"));
54 return GNUNET_NO;
55 }
56 return GNUNET_OK;
57}
58
59
60const char *
62{
63 static char buf[sizeof(struct GNUNET_CRYPTO_PublicKey) * 8];
64 char *end;
65
66 end = GNUNET_STRINGS_data_to_string ((const unsigned char *) z,
67 sizeof(struct
69 buf, sizeof(buf));
70 if (NULL == end)
71 {
72 GNUNET_break (0);
73 return NULL;
74 }
75 *end = '\0';
76 return buf;
77}
78
79
91 const struct GNUNET_GNSRECORD_Data *b)
92{
94 "Comparing records\n");
95 if (a->record_type != b->record_type)
96 {
98 "Record type %u != %u\n", a->record_type, b->record_type);
99 return GNUNET_NO;
100 }
101 if ((a->expiration_time != b->expiration_time) &&
102 ((a->expiration_time != 0) && (b->expiration_time != 0)))
103 {
105 "Expiration time %llu != %llu\n",
106 (unsigned long long) a->expiration_time,
107 (unsigned long long) b->expiration_time);
108 return GNUNET_NO;
109 }
112 {
114 "Flags %u (%u) != %u (%u)\n", a->flags,
117 return GNUNET_NO;
118 }
119 if (a->data_size != b->data_size)
120 {
122 "Data size %llu != %llu\n",
123 (unsigned long long) a->data_size,
124 (unsigned long long) b->data_size);
125 return GNUNET_NO;
126 }
127 if (0 != memcmp (a->data, b->data, a->data_size))
128 {
130 "Data contents do not match\n");
131 return GNUNET_NO;
132 }
134 "Records are equal\n");
135 return GNUNET_YES;
136}
137
138
141 const struct
144{
146 struct GNUNET_TIME_Absolute at;
147 struct GNUNET_TIME_Relative rt;
148 struct GNUNET_TIME_Absolute at_shadow;
149 struct GNUNET_TIME_Relative rt_shadow;
150
151 if (0 == rd_count)
154 for (unsigned int c = 0; c < rd_count; c++)
155 {
156 if (0 != (rd[c].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
157 {
160 }
161 else
162 {
164 }
165
166 for (unsigned int c2 = 0; c2 < rd_count; c2++)
167 {
168 /* Check for shadow record */
169 if ((c == c2) ||
170 (rd[c].record_type != rd[c2].record_type) ||
171 (0 == (rd[c2].flags & GNUNET_GNSRECORD_RF_SHADOW)))
172 continue;
173 /* We have a shadow record */
174 if (0 != (rd[c2].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
175 {
176 rt_shadow.rel_value_us = rd[c2].expiration_time;
177 at_shadow = GNUNET_TIME_relative_to_absolute (rt_shadow);
178 }
179 else
180 {
181 at_shadow.abs_value_us = rd[c2].expiration_time;
182 }
184 at_shadow);
185 }
187 expire);
188 }
191 "Determined expiration time for block with %u records to be %s\n",
192 rd_count,
194 return expire;
195}
196
197
204int
206{
207 struct GNUNET_TIME_Absolute at;
208
210 return GNUNET_NO;
212 return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value_us) ?
214}
215
216
227const char *
229{
230 static char ret[128];
231 char *pkeys;
232
235 sizeof(ret),
236 "%s",
237 pkeys);
238 GNUNET_free (pkeys);
239 return ret;
240}
241
242
252int
255{
256 if (GNUNET_OK !=
258 pkey))
259 return GNUNET_SYSERR;
260 return GNUNET_OK;
261}
262
263
266 size_t data_size,
267 uint32_t type,
269{
271 return GNUNET_SYSERR;
272 switch (type)
273 {
275 if (data_size > sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))
276 return GNUNET_SYSERR;
277 memcpy (&key->ecdsa_key, data, data_size);
278 break;
280 if (data_size > sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))
281 return GNUNET_SYSERR;
282 memcpy (&key->eddsa_key, data, data_size);
283 break;
284 default:
285 return GNUNET_NO;
286 }
287 key->type = htonl (type);
288
289 return GNUNET_YES;
290}
291
292
296 char **data,
297 size_t *data_size,
298 uint32_t *type)
299{
300 char *tmp;
301 *type = ntohl (key->type);
303 if (0 == *data_size)
304 return GNUNET_SYSERR;
305 tmp = GNUNET_malloc (*data_size);
306 memcpy (tmp, ((char*) key) + sizeof (key->type), *data_size);
307 *data = tmp;
308 return GNUNET_OK;
309}
310
311
314{
315 switch (type)
316 {
319 return GNUNET_YES;
320 default:
321 return GNUNET_NO;
322 }
323}
324
325
326size_t
328{
329 return ntohl (block->size);
330}
331
332
336{
337
338 switch (ntohl (block->type))
339 {
341 return GNUNET_TIME_absolute_ntoh (block->ecdsa_block.expiration_time);
343 return GNUNET_TIME_absolute_ntoh (block->eddsa_block.expiration_time);
344 default:
345 GNUNET_break (0); /* Hopefully we never get here, but we might */
346 }
348
349}
350
351
354 struct GNUNET_HashCode *query)
355{
356 switch (ntohl (block->type))
357 {
360 sizeof (block->ecdsa_block.derived_key),
361 query);
362 return GNUNET_OK;
365 sizeof (block->eddsa_block.derived_key),
366 query);
367 return GNUNET_OK;
368 default:
369 return GNUNET_SYSERR;
370 }
371 return GNUNET_SYSERR;
372
373}
374
375
378 const struct
380 unsigned int rd_count,
381 struct GNUNET_GNSRECORD_Data *
382 rd_public,
383 unsigned int *rd_count_public,
384 struct GNUNET_TIME_Absolute *expiry,
386 char **emsg)
387{
388 struct GNUNET_TIME_Absolute now;
389 struct GNUNET_TIME_Absolute minimum_expiration;
390 int have_zone_delegation = GNUNET_NO;
391 int have_gns2dns = GNUNET_NO;
392 int have_other = GNUNET_NO;
393 int have_redirect = GNUNET_NO;
394 int have_empty_label = (0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, label));
395 unsigned int rd_count_tmp;
396
397 minimum_expiration = GNUNET_TIME_UNIT_ZERO_ABS;
399 rd_count_tmp = 0;
400 for (unsigned int i = 0; i < rd_count; i++)
401 {
402 /* Ignore private records for public record set */
404 (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)))
405 {
407 "Filtering private record filter=%u...\n", filter);
408 continue;
409 }
410 /* Skip expired records */
411 if ((0 == (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) &&
412 (rd[i].expiration_time < now.abs_value_us))
413 {
415 "Filtering expired record...\n");
416 continue; /* record already expired, skip it */
417 }
418 /* Ignore the maintenance record (e.g. tombstone) unless filter permits explicitly.
419 * Remember expiration time. */
420 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_MAINTENANCE))
421 {
423 {
424 rd_public[rd_count_tmp] = rd[i];
425 rd_count_tmp++;
426 }
427 continue;
428 }
429 /* No NICK records unless empty label */
430 if (have_empty_label &&
431 (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type))
432 continue;
433
443 if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type))
444 {
445 /* No delegation records under empty label*/
446 if (have_empty_label)
447 {
448 *emsg = GNUNET_strdup (_ (
449 "Zone delegation record not allowed in apex."));
450 return GNUNET_SYSERR;
451 }
452 if ((GNUNET_YES == have_other) ||
453 (GNUNET_YES == have_redirect) ||
454 (GNUNET_YES == have_gns2dns))
455 {
456 *emsg = GNUNET_strdup (_ (
457 "Zone delegation record set contains mutually exclusive records."));
458 return GNUNET_SYSERR;
459 }
460 have_zone_delegation = GNUNET_YES;
461 }
462 else if (GNUNET_GNSRECORD_TYPE_REDIRECT == rd[i].record_type)
463 {
464 if (GNUNET_YES == have_redirect)
465 {
466 *emsg = GNUNET_strdup (_ (
467 "Multiple REDIRECT records."));
468 return GNUNET_SYSERR;
469
470 }
471 if ((GNUNET_YES == have_other) ||
472 (GNUNET_YES == have_zone_delegation) ||
473 (GNUNET_YES == have_gns2dns))
474 {
475 *emsg = GNUNET_strdup (_ (
476 "Redirection record set contains mutually exclusive records."));
477 return GNUNET_SYSERR;
478 }
479 /* No redirection records under empty label*/
480 if (have_empty_label)
481 {
482 *emsg = GNUNET_strdup (_ (
483 "Redirection records not allowed in apex."));
484 return GNUNET_SYSERR;
485 }
486 have_redirect = GNUNET_YES;
487 }
488 else if (GNUNET_GNSRECORD_TYPE_GNS2DNS == rd[i].record_type)
489 {
490 /* No gns2dns records under empty label*/
491 if (have_empty_label)
492 {
493 *emsg = GNUNET_strdup (_ (
494 "Redirection records not allowed in apex.."));
495 return GNUNET_SYSERR;
496 }
497 if ((GNUNET_YES == have_other) ||
498 (GNUNET_YES == have_redirect) ||
499 (GNUNET_YES == have_zone_delegation))
500 {
501 *emsg = GNUNET_strdup (_ (
502 "Redirection record set contains mutually exclusive records."));
503 return GNUNET_SYSERR;
504 }
505 have_gns2dns = GNUNET_YES;
506 }
507 else
508 {
509 /* Some other record.
510 * Not allowed for zone delegations or redirections */
511 if ((GNUNET_YES == have_zone_delegation) ||
512 (GNUNET_YES == have_redirect) ||
513 (GNUNET_YES == have_gns2dns))
514 {
515 *emsg = GNUNET_strdup (_ (
516 "Mutually exclusive records."));
517 return GNUNET_SYSERR;
518 }
519 have_other = GNUNET_YES;
520 }
521
522 rd_public[rd_count_tmp] = rd[i];
523 /* Make sure critical record types are marked as such */
524 if (GNUNET_YES == GNUNET_GNSRECORD_is_critical (rd[i].record_type))
525 rd_public[rd_count_tmp].flags |= GNUNET_GNSRECORD_RF_CRITICAL;
526 rd_count_tmp++;
527 }
528
529 *expiry = GNUNET_GNSRECORD_record_get_expiration_time (rd_count_tmp,
530 rd_public,
531 minimum_expiration);
532 *rd_count_public = rd_count_tmp;
533 return GNUNET_OK;
534}
535
536
537/* end of gnsrecord_misc.c */
#define LOG(kind,...)
static int ret
Final status code.
Definition: gnunet-arm.c:93
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:33
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 Attribute String.
Definition: gnunet-did.c:97
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:239
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:85
#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:379
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:399
@ 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:732
char * GNUNET_STRINGS_utf8_normalize(const char *input)
Normalize the utf-8 input string to NFC.
Definition: strings.c:438
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:406
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:368
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:741
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:360
#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:640
#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.