From afd2cb5db220ce528b6222340b31b8a1a365c8e4 Mon Sep 17 00:00:00 2001 From: Martin Schanzenbach Date: Thu, 3 Feb 2022 18:44:40 +0100 Subject: GNS: Introduce REDIRECT records. Fixes #7172 --- src/gns/gnunet-service-gns_resolver.c | 127 +++++++++++++++++++++++++++++----- src/gns/plugin_gnsrecord_gns.c | 8 +-- 2 files changed, 112 insertions(+), 23 deletions(-) (limited to 'src/gns') diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c index f232fb272..461257609 100644 --- a/src/gns/gnunet-service-gns_resolver.c +++ b/src/gns/gnunet-service-gns_resolver.c @@ -1235,16 +1235,16 @@ recursive_dns_resolution (struct GNS_ResolverHandle *rh) /** - * We encountered a CNAME record during our resolution. + * We encountered a REDIRECT record during our resolution. * Merge it into our chain. * * @param rh resolution we are performing - * @param cname value of the cname record we got for the current + * @param rname value of the redirect record we got for the current * authority chain tail */ static void -handle_gns_cname_result (struct GNS_ResolverHandle *rh, - const char *cname) +handle_gns_redirect_result (struct GNS_ResolverHandle *rh, + const char *rname) { size_t nlen; char *res; @@ -1253,14 +1253,14 @@ handle_gns_cname_result (struct GNS_ResolverHandle *rh, int af; struct GNUNET_IDENTITY_PublicKey zone; - nlen = strlen (cname); - tld = GNS_get_tld (cname); + nlen = strlen (rname); + tld = GNS_get_tld (rname); if (0 == strcmp ("+", tld)) { - /* CNAME resolution continues relative to current domain */ + /* REDIRECT resolution continues relative to current domain */ if (0 == rh->name_resolution_pos) { - res = GNUNET_strndup (cname, nlen - 2); + res = GNUNET_strndup (rname, nlen - 2); rh->name_resolution_pos = nlen - 2; } else @@ -1270,7 +1270,7 @@ handle_gns_cname_result (struct GNS_ResolverHandle *rh, (int) rh->name_resolution_pos, rh->name, (int) (nlen - 2), - cname); + rname); rh->name_resolution_pos = strlen (res); } GNUNET_free (rh->name); @@ -1291,13 +1291,13 @@ handle_gns_cname_result (struct GNS_ResolverHandle *rh, } if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)) { - /* CNAME resolution continues relative to current domain */ + /* REDIRECT resolution continues relative to current domain */ if (0 == rh->name_resolution_pos) { GNUNET_asprintf (&res, "%.*s", - (int) (strlen (cname) - (strlen (tld) + 1)), - cname); + (int) (strlen (rname) - (strlen (tld) + 1)), + rname); } else { @@ -1305,8 +1305,8 @@ handle_gns_cname_result (struct GNS_ResolverHandle *rh, "%.*s.%.*s", (int) rh->name_resolution_pos, rh->name, - (int) (strlen (cname) - (strlen (tld) + 1)), - cname); + (int) (strlen (rname) - (strlen (tld) + 1)), + rname); } rh->name_resolution_pos = strlen (res); GNUNET_free (rh->name); @@ -1326,17 +1326,63 @@ handle_gns_cname_result (struct GNS_ResolverHandle *rh, } GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Got CNAME `%s' from GNS for `%s'\n", - cname, + "Got REDIRECT `%s' from GNS for `%s'\n", + rname, rh->name); if (NULL != rh->std_resolve) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Multiple CNAME results from GNS resolving `%s'! Not really allowed...\n", + "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n", rh->name); GNUNET_RESOLVER_request_cancel (rh->std_resolve); } /* name is absolute, go to DNS */ + GNUNET_free (rh->name); + rh->name = GNUNET_strdup (rname); + rh->name_resolution_pos = strlen (rh->name); + switch (rh->record_type) + { + case GNUNET_DNSPARSER_TYPE_A: + af = AF_INET; + break; + + case GNUNET_DNSPARSER_TYPE_AAAA: + af = AF_INET6; + break; + + default: + af = AF_UNSPEC; + break; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Doing standard DNS lookup for `%s'\n", + rh->name); + + rh->std_resolve = GNUNET_RESOLVER_ip_get (rh->name, + af, + DNS_LOOKUP_TIMEOUT, + &handle_dns_result, + rh); +} + + + +/** + * We encountered a CNAME record during our resolution. + * Merge it into our chain. + * + * @param rh resolution we are performing + * @param cname value of the cname record we got for the current + * authority chain tail + */ +static void +handle_gns_cname_result (struct GNS_ResolverHandle *rh, + const char *cname) +{ + struct AuthorityChain *ac; + int af; + struct GNUNET_IDENTITY_PublicKey zone; + GNUNET_free (rh->name); rh->name = GNUNET_strdup (cname); rh->name_resolution_pos = strlen (rh->name); @@ -1653,6 +1699,20 @@ handle_gns2dns_ip (void *cls, ac->authority_info.dns_authority.found = GNUNET_YES; } +/** + * We found a REDIRECT record, perform recursive resolution on it. + * + * @param rh resolution handle + * @param rd record with CNAME to resolve recursively + */ +static void +recursive_redirect_resolution (struct GNS_ResolverHandle *rh, + const struct GNUNET_GNSRECORD_Data *rd) +{ + handle_gns_redirect_result (rh, + rd->data); +} + /** * We found a CNAME record, perform recursive resolution on it. @@ -2006,6 +2066,16 @@ handle_gns_resolution_result (void *cls, GNUNET_free (cname); return; } + if ((rd_count > 0) && + (GNUNET_GNSRECORD_TYPE_REDIRECT == rd[0].record_type) && + (GNUNET_GNSRECORD_TYPE_REDIRECT != rh->record_type)) + { + handle_gns_cname_result (rh, + rd[0].data); + return; + } + + /* If A/AAAA was requested, but we got a VPN record, we convert it to A/AAAA using GNUnet VPN */ if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) || @@ -2117,6 +2187,23 @@ handle_gns_resolution_result (void *cls, so we can free it afterwards. */ switch (rd[i].record_type) { + case GNUNET_GNSRECORD_TYPE_REDIRECT: + { + char *rname; + rname = GNUNET_strndup (rd[i].data, rd[i].data_size); + rname = translate_dot_plus (rh, rname); + GNUNET_break (NULL != rname); + scratch_start = scratch_off; + memcpy (&scratch[scratch_start], rname, strlen (rname) + 1); + scratch_off += strlen (rname) + 1; + GNUNET_assert (rd_off < rd_count); + rd_new[rd_off].data = &scratch[scratch_start]; + rd_new[rd_off].data_size = scratch_off - scratch_start; + rd_off++; + GNUNET_free (rname); + } + break; + case GNUNET_DNSPARSER_TYPE_CNAME: { char *cname; @@ -2380,6 +2467,12 @@ handle_gns_resolution_result (void *cls, switch (rd[0].record_type) { + case GNUNET_GNSRECORD_TYPE_REDIRECT: + GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */ + recursive_redirect_resolution (rh, + &rd[0]); + return; + case GNUNET_DNSPARSER_TYPE_CNAME: GNUNET_break_op (1 == rd_count); /* CNAME should be unique */ recursive_cname_resolution (rh, diff --git a/src/gns/plugin_gnsrecord_gns.c b/src/gns/plugin_gnsrecord_gns.c index f270e4473..e74ec96ad 100644 --- a/src/gns/plugin_gnsrecord_gns.c +++ b/src/gns/plugin_gnsrecord_gns.c @@ -64,8 +64,7 @@ gns_value_to_string (void *cls, return GNUNET_IDENTITY_public_key_to_string (&pk); case GNUNET_GNSRECORD_TYPE_NICK: - return GNUNET_strndup (data, data_size); - + case GNUNET_GNSRECORD_TYPE_REDIRECT: case GNUNET_GNSRECORD_TYPE_LEHO: return GNUNET_strndup (data, data_size); @@ -190,10 +189,7 @@ gns_string_to_value (void *cls, return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_NICK: - *data = GNUNET_strdup (s); - *data_size = strlen (s); - return GNUNET_OK; - + case GNUNET_GNSRECORD_TYPE_REDIRECT: case GNUNET_GNSRECORD_TYPE_LEHO: *data = GNUNET_strdup (s); *data_size = strlen (s); -- cgit v1.2.3