From 32f590da99c8c77c063b58e3a105a3c05fa5e988 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 5 Apr 2018 16:25:46 +0200 Subject: [PATCH] where applicable, check DNS ID in responses before processing further --- src/dns/dnsstub.c | 85 +++++++++++++++++++-------- src/dns/gnunet-service-dns.c | 3 + src/exit/gnunet-daemon-exit.c | 2 + src/gns/gnunet-dns2gns.c | 23 +++++++- src/gns/gnunet-service-gns_resolver.c | 27 +++++++-- src/include/gnunet_dns_service.h | 9 +-- src/include/gnunet_dnsparser_lib.h | 1 + 7 files changed, 114 insertions(+), 36 deletions(-) diff --git a/src/dns/dnsstub.c b/src/dns/dnsstub.c index 364b6fe28..c79502ce9 100644 --- a/src/dns/dnsstub.c +++ b/src/dns/dnsstub.c @@ -235,8 +235,22 @@ get_request_socket (struct GNUNET_DNSSTUB_Context *ctx, struct GNUNET_DNSSTUB_RequestSocket *rs; struct GNUNET_NETWORK_FDSet *rset; - rs = &ctx->sockets[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, - DNS_SOCKET_MAX)]; + for (unsigned int i=0;i<256;i++) + { + rs = &ctx->sockets[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, + DNS_SOCKET_MAX)]; + if (NULL == rs->rc) + break; + } + if (NULL != rs->rc) + { + /* signal "failure" */ + rs->rc (rs->rc_cls, + rs, + NULL, + 0); + rs->rc = NULL; + } rs->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT); switch (af) { @@ -271,9 +285,11 @@ get_request_socket (struct GNUNET_DNSSTUB_Context *ctx, return NULL; rset = GNUNET_NETWORK_fdset_create (); if (NULL != rs->dnsout4) - GNUNET_NETWORK_fdset_set (rset, rs->dnsout4); + GNUNET_NETWORK_fdset_set (rset, + rs->dnsout4); if (NULL != rs->dnsout6) - GNUNET_NETWORK_fdset_set (rset, rs->dnsout6); + GNUNET_NETWORK_fdset_set (rset, + rs->dnsout6); rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, REQUEST_TIMEOUT, rset, @@ -326,11 +342,11 @@ transmit_query (void *cls) * * @param ctx stub resolver to use * @param sa the socket address - * @param sa_len the socket length + * @param sa_len the length of @a sa * @param request DNS request to transmit - * @param request_len number of bytes in msg + * @param request_len number of bytes in @a request * @param rc function to call with result - * @param rc_cls closure for 'rc' + * @param rc_cls closure for @a rc * @return socket used for the request, NULL on error */ struct GNUNET_DNSSTUB_RequestSocket * @@ -347,6 +363,7 @@ GNUNET_DNSSTUB_resolve (struct GNUNET_DNSSTUB_Context *ctx, if (NULL == (rs = get_request_socket (ctx, sa->sa_family))) return NULL; + GNUNET_assert (NULL == rs->rc); GNUNET_memcpy (&rs->addr, sa, sa_len); @@ -389,7 +406,9 @@ GNUNET_DNSSTUB_resolve2 (struct GNUNET_DNSSTUB_Context *ctx, memset (&v4, 0, sizeof (v4)); memset (&v6, 0, sizeof (v6)); - if (1 == inet_pton (AF_INET, ctx->dns_exit, &v4.sin_addr)) + if (1 == inet_pton (AF_INET, + ctx->dns_exit, + &v4.sin_addr)) { salen = sizeof (v4); v4.sin_family = AF_INET; @@ -400,7 +419,9 @@ GNUNET_DNSSTUB_resolve2 (struct GNUNET_DNSSTUB_Context *ctx, sa = (struct sockaddr *) &v4; af = AF_INET; } - else if (1 == inet_pton (AF_INET6, ctx->dns_exit, &v6.sin6_addr)) + else if (1 == inet_pton (AF_INET6, + ctx->dns_exit, + &v6.sin6_addr)) { salen = sizeof (v6); v6.sin6_family = AF_INET6; @@ -416,8 +437,10 @@ GNUNET_DNSSTUB_resolve2 (struct GNUNET_DNSSTUB_Context *ctx, GNUNET_break (0); return NULL; } - if (NULL == (rs = get_request_socket (ctx, af))) + if (NULL == (rs = get_request_socket (ctx, + af))) return NULL; + GNUNET_assert (NULL == rs->rc); if (NULL != rs->dnsout4) dnsout = rs->dnsout4; else @@ -430,15 +453,17 @@ GNUNET_DNSSTUB_resolve2 (struct GNUNET_DNSSTUB_Context *ctx, return NULL; } GNUNET_memcpy (&rs->addr, - sa, - salen); + sa, + salen); rs->addrlen = salen; rs->rc = rc; rs->rc_cls = rc_cls; if (GNUNET_SYSERR == GNUNET_NETWORK_socket_sendto (dnsout, request, - request_len, sa, salen)) + request_len, + sa, + salen)) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to send DNS request to %s\n"), GNUNET_a2s (sa, salen)); @@ -466,7 +491,9 @@ do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs, int len; #ifndef MINGW - if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), FIONREAD, &len)) + if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), + FIONREAD, + &len)) { /* conservative choice: */ len = UINT16_MAX; @@ -484,11 +511,14 @@ do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs, addrlen = sizeof (addr); memset (&addr, 0, sizeof (addr)); r = GNUNET_NETWORK_socket_recvfrom (dnsout, - buf, sizeof (buf), - (struct sockaddr*) &addr, &addrlen); + buf, + sizeof (buf), + (struct sockaddr*) &addr, + &addrlen); if (-1 == r) { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom"); + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "recvfrom"); GNUNET_NETWORK_socket_close (dnsout); return GNUNET_SYSERR; } @@ -543,25 +573,32 @@ read_response (void *cls) } /* read and process ready sockets */ if ((NULL != rs->dnsout4) && - (GNUNET_NETWORK_fdset_isset (tc->read_ready, rs->dnsout4)) && - (GNUNET_SYSERR == do_dns_read (rs, rs->dnsout4))) + (GNUNET_NETWORK_fdset_isset (tc->read_ready, + rs->dnsout4)) && + (GNUNET_SYSERR == do_dns_read (rs, + rs->dnsout4))) rs->dnsout4 = NULL; if ((NULL != rs->dnsout6) && - (GNUNET_NETWORK_fdset_isset (tc->read_ready, rs->dnsout6)) && - (GNUNET_SYSERR == do_dns_read (rs, rs->dnsout6))) + (GNUNET_NETWORK_fdset_isset (tc->read_ready, + rs->dnsout6)) && + (GNUNET_SYSERR == do_dns_read (rs, + rs->dnsout6))) rs->dnsout6 = NULL; /* re-schedule read task */ rset = GNUNET_NETWORK_fdset_create (); if (NULL != rs->dnsout4) - GNUNET_NETWORK_fdset_set (rset, rs->dnsout4); + GNUNET_NETWORK_fdset_set (rset, + rs->dnsout4); if (NULL != rs->dnsout6) - GNUNET_NETWORK_fdset_set (rset, rs->dnsout6); + GNUNET_NETWORK_fdset_set (rset, + rs->dnsout6); rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_TIME_absolute_get_remaining (rs->timeout), rset, NULL, - &read_response, rs); + &read_response, + rs); GNUNET_NETWORK_fdset_destroy (rset); } diff --git a/src/dns/gnunet-service-dns.c b/src/dns/gnunet-service-dns.c index ffc94afb7..9feaa8413 100644 --- a/src/dns/gnunet-service-dns.c +++ b/src/dns/gnunet-service-dns.c @@ -729,6 +729,9 @@ process_dns_result (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing DNS result from stub resolver\n"); GNUNET_assert (NULL == cls); + if (NULL == dns) + return; /* ignore */ + rr = &requests[dns->id]; if ( (rr->phase != RP_INTERNET_DNS) || (rr->rs != rs) ) diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c index c624e083e..0b3cc505a 100644 --- a/src/exit/gnunet-daemon-exit.c +++ b/src/exit/gnunet-daemon-exit.c @@ -475,6 +475,8 @@ process_dns_result (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing DNS result from stub resolver\n"); GNUNET_assert (NULL == cls); + if (NULL == dns) + return; /* Handle case that this is a reply to a request from a CADET DNS channel */ ts = channels[dns->id]; if ( (NULL == ts) || diff --git a/src/gns/gnunet-dns2gns.c b/src/gns/gnunet-dns2gns.c index 3d16cd773..47cc6dde0 100644 --- a/src/gns/gnunet-dns2gns.c +++ b/src/gns/gnunet-dns2gns.c @@ -85,6 +85,11 @@ struct Request * Number of bytes in @e udp_msg. */ size_t udp_msg_size; + + /** + * ID of the original request. + */ + uint16_t original_request_id; }; @@ -255,6 +260,18 @@ dns_result_processor (void *cls, struct Request *request = cls; (void) rs; + if (NULL == dns) + { + /* DNSSTUB gave up, so we trigger timeout early */ + GNUNET_SCHEDULER_cancel (request->timeout_task); + do_timeout (request); + return; + } + if (request->original_request_id != dns->id) + { + /* for a another query, ignore */ + return; + } request->packet = GNUNET_DNSPARSER_parse ((char*)dns, r); send_response (request); @@ -277,7 +294,6 @@ result_processor (void *cls, { struct Request *request = cls; struct GNUNET_DNSPARSER_Packet *packet; - uint32_t i; struct GNUNET_DNSPARSER_Record rec; request->lookup = NULL; @@ -288,6 +304,7 @@ result_processor (void *cls, "Using DNS resolver IP `%s' to resolve `%s'\n", dns_ip, request->packet->queries[0].name); + request->original_request_id = request->packet->id; GNUNET_DNSPARSER_free_packet (request->packet); request->packet = NULL; request->dns_lookup = GNUNET_DNSSTUB_resolve2 (dns_stub, @@ -296,7 +313,7 @@ result_processor (void *cls, &dns_result_processor, request); return; - } + } packet = request->packet; packet->flags.query_or_response = 1; packet->flags.return_code = GNUNET_TUN_DNS_RETURN_CODE_NO_ERROR; @@ -307,7 +324,7 @@ result_processor (void *cls, packet->flags.message_truncated = 0; packet->flags.authoritative_answer = 0; //packet->flags.opcode = GNUNET_TUN_DNS_OPCODE_STATUS; // ??? - for (i=0;idns_request = NULL; - GNUNET_SCHEDULER_cancel (rh->task_id); - rh->task_id = NULL; + if (NULL == dns) + { + rh->dns_request = NULL; + GNUNET_SCHEDULER_cancel (rh->task_id); + rh->task_id = NULL; + rh->proc (rh->proc_cls, + 0, + NULL); + GNS_resolver_lookup_cancel (rh); + return; + } + if (rh->original_dns_id != dns->id) + { + /* DNS answer, but for another query */ + return; + } p = GNUNET_DNSPARSER_parse ((const char *) dns, dns_len); if (NULL == p) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to parse DNS response\n")); - rh->proc (rh->proc_cls, 0, NULL); - GNS_resolver_lookup_cancel (rh); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -1097,6 +1113,7 @@ recursive_dns_resolution (struct GNS_ResolverHandle *rh) } else { + rh->original_dns_id = p->id; rh->dns_request = GNUNET_DNSSTUB_resolve (dns_handle, (const struct sockaddr *) &ac->authority_info.dns_authority.dns_ip, sa_len, diff --git a/src/include/gnunet_dns_service.h b/src/include/gnunet_dns_service.h index 76b708dcf..017d5a039 100644 --- a/src/include/gnunet_dns_service.h +++ b/src/include/gnunet_dns_service.h @@ -122,10 +122,11 @@ enum GNUNET_DNS_Flags * @param request_length number of bytes in request * @param request udp payload of the DNS request */ -typedef void (*GNUNET_DNS_RequestHandler)(void *cls, - struct GNUNET_DNS_RequestHandle *rh, - size_t request_length, - const char *request); +typedef void +(*GNUNET_DNS_RequestHandler)(void *cls, + struct GNUNET_DNS_RequestHandle *rh, + size_t request_length, + const char *request); /** diff --git a/src/include/gnunet_dnsparser_lib.h b/src/include/gnunet_dnsparser_lib.h index 9fe3491d6..80a67c3c7 100644 --- a/src/include/gnunet_dnsparser_lib.h +++ b/src/include/gnunet_dnsparser_lib.h @@ -49,6 +49,7 @@ /** * A few common DNS types. */ +#define GNUNET_DNSPARSER_TYPE_ANY 0 #define GNUNET_DNSPARSER_TYPE_A 1 #define GNUNET_DNSPARSER_TYPE_NS 2 #define GNUNET_DNSPARSER_TYPE_CNAME 5 -- 2.25.1