GNUnet  0.17.6
plugin_gnsrecord_gns.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2013, 2014, 2016 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 
29 #include "platform.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_gnsrecord_lib.h"
32 #include "gnunet_dnsparser_lib.h"
34 #include <inttypes.h>
35 
36 
46 static char *
48  uint32_t type,
49  const void *data,
50  size_t data_size)
51 {
52  const char *cdata;
54 
55  switch (type)
56  {
59  if (GNUNET_OK !=
61  data_size,
62  type,
63  &pk))
64  return NULL;
66 
70  return GNUNET_strndup (data, data_size);
71 
73  char *ns;
74  char *ip;
75  size_t off;
76  char *nstr;
77 
78  off = 0;
80  if (NULL == ns)
81  {
82  GNUNET_break_op (0);
83  GNUNET_free (ns);
84  return NULL;
85  }
86  /* DNS server IP/name must be UTF-8 */
87  ip = GNUNET_strdup (&((const char*) data)[off]);
88  GNUNET_asprintf (&nstr, "%s@%s", ns, ip);
89  GNUNET_free (ns);
90  GNUNET_free (ip);
91  return nstr;
92  }
93 
95  struct GNUNET_TUN_GnsVpnRecord vpn;
96  char *vpn_str;
97 
98  cdata = data;
99  if ((data_size <= sizeof(vpn)) || ('\0' != cdata[data_size - 1]))
100  return NULL; /* malformed */
101  /* need to memcpy for alignment */
102  GNUNET_memcpy (&vpn, data, sizeof(vpn));
103  GNUNET_asprintf (&vpn_str,
104  "%u %s %s",
105  (unsigned int) ntohs (vpn.proto),
106  (const char *) GNUNET_i2s_full (&vpn.peer),
107  (const char *) &cdata[sizeof(vpn)]);
108  return vpn_str;
109  }
110 
112  struct GNUNET_GNSRECORD_BoxRecord box;
113  uint32_t rt;
114  char *box_str;
115  char *ival;
116 
117  cdata = data;
118  if (data_size < sizeof(struct GNUNET_GNSRECORD_BoxRecord))
119  return NULL; /* malformed */
120  GNUNET_memcpy (&box, data, sizeof(box));
121  rt = ntohl (box.record_type);
123  &cdata[sizeof(box)],
124  data_size - sizeof(box));
125  if (NULL == ival)
126  return NULL; /* malformed */
127  GNUNET_asprintf (&box_str,
128  "%u %u %u %s",
129  (unsigned int) ntohs (box.protocol),
130  (unsigned int) ntohs (box.service),
131  (unsigned int) rt,
132  ival);
133  GNUNET_free (ival);
134  return box_str;
135  }
137  return GNUNET_strdup (_ (
138  "This is a memento of an older block for internal maintenance."));
139  }
140  default:
141  return NULL;
142  }
143 }
144 
145 
157 static int
159  uint32_t type,
160  const char *s,
161  void **data,
162  size_t *data_size)
163 {
165  uint32_t record_type;
166 
167  if (NULL == s)
168  return GNUNET_SYSERR;
169  switch (type)
170  {
173  if (GNUNET_OK !=
175  {
177  _ ("Unable to parse zone key record `%s'\n"),
178  s);
179  return GNUNET_SYSERR;
180  }
182  if (GNUNET_OK !=
184  (char **) data,
185  data_size,
186  &record_type))
187  return GNUNET_SYSERR;
188  if (record_type != type)
189  {
191  _ ("Record type does not match parsed record type\n"));
192  return GNUNET_SYSERR;
193  }
194  return GNUNET_OK;
195 
199  *data = GNUNET_strdup (s);
200  *data_size = strlen (s);
201  return GNUNET_OK;
202 
204  char nsbuf[514];
205  char *cpy;
206  char *at;
207  size_t off;
208 
209  cpy = GNUNET_strdup (s);
210  at = strchr (cpy, '@');
211  if (NULL == at)
212  {
214  _ ("Unable to parse GNS2DNS record `%s'\n"),
215  s);
216  GNUNET_free (cpy);
217  return GNUNET_SYSERR;
218  }
219  *at = '\0';
220  at++;
221 
222  off = 0;
223  if (GNUNET_OK !=
225  sizeof(nsbuf),
226  &off,
227  cpy))
228  {
230  _ (
231  "Failed to serialize GNS2DNS record with value `%s': Not a DNS name.\n"),
232  s);
233  GNUNET_free (cpy);
234  return GNUNET_SYSERR;
235  }
236  /* The DNS server location/name is in UTF-8 */
237  GNUNET_memcpy (&nsbuf[off], at, strlen (at) + 1);
238  off += strlen (at) + 1;
239  GNUNET_free (cpy);
240  *data_size = off;
241  *data = GNUNET_malloc (off);
242  GNUNET_memcpy (*data, nsbuf, off);
243  return GNUNET_OK;
244  }
245 
247  struct GNUNET_TUN_GnsVpnRecord *vpn;
248  char s_peer[103 + 1];
249  char s_serv[253 + 1];
250  unsigned int proto;
251 
252  if (3 != sscanf (s, "%u %103s %253s", &proto, s_peer, s_serv))
253  {
255  _ ("Unable to parse VPN record string `%s'\n"),
256  s);
257  return GNUNET_SYSERR;
258  }
259  *data_size = sizeof(struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1;
260  *data = vpn = GNUNET_malloc (*data_size);
261  if (GNUNET_OK !=
263  strlen (s_peer),
264  &vpn->peer.public_key))
265  {
266  GNUNET_free (vpn);
267  *data_size = 0;
268  return GNUNET_SYSERR;
269  }
270  vpn->proto = htons ((uint16_t) proto);
271  strcpy ((char *) &vpn[1], s_serv);
272  return GNUNET_OK;
273  }
274 
276  struct GNUNET_GNSRECORD_BoxRecord *box;
277  size_t rest;
278  unsigned int protocol;
279  unsigned int service;
280  unsigned int record_type;
281  void *bval;
282  size_t bval_size;
283 
284  if (3 != sscanf (s, "%u %u %u ", &protocol, &service, &record_type))
285  {
287  _ ("Unable to parse BOX record string `%s'\n"),
288  s);
289  return GNUNET_SYSERR;
290  }
291  rest = snprintf (NULL, 0, "%u %u %u ", protocol, service, record_type);
293  &s[rest],
294  &bval,
295  &bval_size))
296  return GNUNET_SYSERR;
297  *data_size = sizeof(struct GNUNET_GNSRECORD_BoxRecord) + bval_size;
298  *data = box = GNUNET_malloc (*data_size);
299  box->protocol = htons (protocol);
300  box->service = htons (service);
301  box->record_type = htonl (record_type);
302  GNUNET_memcpy (&box[1], bval, bval_size);
303  GNUNET_free (bval);
304  return GNUNET_OK;
305  }
307  *data_size = 0;
308  *data = NULL;
309  return GNUNET_OK;
310  }
311 
312  default:
313  return GNUNET_SYSERR;
314  }
315 }
316 
317 
322 static struct
323 {
324  const char *name;
325  uint32_t number;
326 } gns_name_map[] = {
327  { "PKEY", GNUNET_GNSRECORD_TYPE_PKEY },
328  { "EDKEY", GNUNET_GNSRECORD_TYPE_EDKEY },
329  { "NICK", GNUNET_GNSRECORD_TYPE_NICK },
330  { "LEHO", GNUNET_GNSRECORD_TYPE_LEHO },
331  { "VPN", GNUNET_GNSRECORD_TYPE_VPN },
332  { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS },
333  { "BOX", GNUNET_GNSRECORD_TYPE_BOX },
334  { "REDIRECT", GNUNET_GNSRECORD_TYPE_REDIRECT },
335  /* Tombstones should never be added manually
336  * so this makes sense, kind of */
337  { "\u271E", GNUNET_GNSRECORD_TYPE_TOMBSTONE },
338  { NULL, UINT32_MAX }
339 };
340 
341 
349 static uint32_t
351  const char *gns_typename)
352 {
353  unsigned int i;
354 
355  i = 0;
356  while ((NULL != gns_name_map[i].name) &&
357  (0 != strcasecmp (gns_typename, gns_name_map[i].name)))
358  i++;
359  return gns_name_map[i].number;
360 }
361 
362 
370 static const char *
372  uint32_t type)
373 {
374  unsigned int i;
375 
376  i = 0;
377  while ( (NULL != gns_name_map[i].name) &&
378  (type != gns_name_map[i].number) )
379  i++;
380  return gns_name_map[i].name;
381 }
382 
383 
384 static enum GNUNET_GenericReturnValue
385 gns_is_critical (void *cls, uint32_t type)
386 {
387  return ((type == GNUNET_GNSRECORD_TYPE_PKEY) ||
392 }
393 
394 
401 void *
403 {
405 
412  return api;
413 }
414 
415 
422 void *
424 {
426 
427  GNUNET_free (api);
428  return NULL;
429 }
430 
431 
432 /* end of plugin_gnsrecord_gns.c */
#define GNUNET_GNSRECORD_TYPE_BOX
Boxed records (see TLSA/SRV handling in GNS)
#define GNUNET_GNSRECORD_TYPE_NICK
GNS nick names.
#define GNUNET_GNSRECORD_TYPE_TOMBSTONE
Record type to indicate a previously delete record (PRIVATE only)
#define GNUNET_GNSRECORD_TYPE_GNS2DNS
Delegation to DNS.
#define GNUNET_GNSRECORD_TYPE_REDIRECT
Resolver redirects.
#define GNUNET_GNSRECORD_TYPE_VPN
VPN resolution.
#define GNUNET_GNSRECORD_TYPE_LEHO
legacy hostnames
#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
Record type for EDKEY zone delegations.
static struct GNUNET_NAMESTORE_Handle * ns
Handle to the namestore.
Definition: gnunet-abd.c:41
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
uint32_t data
The data value.
struct GNUNET_IDENTITY_PrivateKey pk
Private key from command line option, or NULL.
static uint8_t proto
Protocol to use.
Definition: gnunet-nat.c:60
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
API for helper library to parse DNS packets.
API that can be used to manipulate GNS record data.
Plugin API for GNS record types.
int GNUNET_DNSPARSER_builder_add_name(char *dst, size_t dst_len, size_t *off, const char *name)
Add a DNS name to the UDP packet at the given location, converting the name to IDNA notation as neces...
Definition: dnsparser.c:889
char * GNUNET_DNSPARSER_parse_name(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse name inside of a DNS query or record.
Definition: dnsparser.c:334
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_identity_from_data(const char *data, size_t data_size, uint32_t type, struct GNUNET_IDENTITY_PublicKey *key)
Build a #GNUNET_GNSRECORD_PublicKey from zone delegation resource record data.
char * GNUNET_GNSRECORD_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the 'value' of a record to a string.
Definition: gnsrecord.c:156
int GNUNET_GNSRECORD_string_to_value(uint32_t type, const char *s, void **data, size_t *data_size)
Convert human-readable version of a 'value' of a record to the binary representation.
Definition: gnsrecord.c:188
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_data_from_identity(const struct GNUNET_IDENTITY_PublicKey *key, char **data, size_t *data_size, uint32_t *type)
Create record data and size from an identity key.
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_public_key_from_string(const char *str, struct GNUNET_IDENTITY_PublicKey *key)
Parses a (Base32) string representation of the public key.
char * GNUNET_IDENTITY_public_key_to_string(const struct GNUNET_IDENTITY_PublicKey *key)
Creates a (Base32) string representation of the public key.
ssize_t GNUNET_IDENTITY_key_get_length(const struct GNUNET_IDENTITY_PublicKey *key)
Get the compacted length of a GNUNET_IDENTITY_PublicKey.
Definition: identity_api.c:991
#define GNUNET_log(kind,...)
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_public_key_from_string(const char *enc, size_t enclen, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Convert a string representing a public key to a public key.
Definition: crypto_ecc.c:357
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:96
@ GNUNET_OK
Definition: gnunet_common.h:99
@ GNUNET_YES
@ GNUNET_NO
Definition: gnunet_common.h:98
@ GNUNET_SYSERR
Definition: gnunet_common.h:97
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_ERROR
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
void * libgnunet_plugin_gnsrecord_gns_init(void *cls)
Entry point for the plugin.
static int gns_string_to_value(void *cls, uint32_t type, const char *s, void **data, size_t *data_size)
Convert human-readable version of a 'value' of a record to the binary representation.
static struct @22 gns_name_map[]
Mapping of record type numbers to human-readable record type names.
const char * name
static const char * gns_number_to_typename(void *cls, uint32_t type)
Convert a type number to the corresponding type string (e.g.
uint32_t number
static uint32_t gns_typename_to_number(void *cls, const char *gns_typename)
Convert a type name (e.g.
static char * gns_value_to_string(void *cls, uint32_t type, const void *data, size_t data_size)
Convert the 'value' of a record to a string.
static enum GNUNET_GenericReturnValue gns_is_critical(void *cls, uint32_t type)
void * libgnunet_plugin_gnsrecord_gns_done(void *cls)
Exit point from the plugin.
Record type used to box up SRV and TLSA records.
uint32_t record_type
GNS record type of the boxed record.
uint16_t service
Service of the boxed record (aka port number), in NBO.
uint16_t protocol
Protocol of the boxed record (6 = TCP, 17 = UDP, etc.).
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
GNUNET_GNSRECORD_IsCriticalFunction is_critical
Is critical.
GNUNET_GNSRECORD_TypenameToNumberFunction typename_to_number
Typename to number.
GNUNET_GNSRECORD_NumberToTypenameFunction number_to_typename
Number to typename.
GNUNET_GNSRECORD_ValueToStringFunction value_to_string
Conversion to string.
void * cls
Closure for all of the callbacks.
GNUNET_GNSRECORD_StringToValueFunction string_to_value
Conversion to binary.
An identity key as per LSD0001.
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Payload of GNS VPN record.
struct GNUNET_PeerIdentity peer
The peer to contact.
uint16_t proto
The protocol to use.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model