From e11a862eed95a9cec122a35b353426d220a7675c Mon Sep 17 00:00:00 2001 From: Danny Sonnenschein Date: Sat, 21 Nov 2020 09:56:22 +0100 Subject: [PATCH] deps: update to c-ares 1.17.1 PR-URL: https://github.com/nodejs/node/pull/36207 Reviewed-By: Matteo Collina Reviewed-By: Shelley Vohr Reviewed-By: Rich Trott --- deps/cares/cares.gyp | 1 + deps/cares/include/ares.h | 13 ++ deps/cares/include/ares_version.h | 4 +- deps/cares/include/nameser.h | 7 + deps/cares/src/ares__readaddrinfo.c | 8 +- deps/cares/src/ares__sortaddrinfo.c | 21 +-- deps/cares/src/ares_data.c | 18 +++ deps/cares/src/ares_data.h | 2 + deps/cares/src/ares_getaddrinfo.c | 11 ++ deps/cares/src/ares_gethostbyaddr.c | 1 - deps/cares/src/ares_gethostbyname.c | 15 +- deps/cares/src/ares_init.c | 20 +-- deps/cares/src/ares_parse_caa_reply.c | 209 ++++++++++++++++++++++++++ deps/cares/src/ares_parse_soa_reply.c | 9 +- deps/cares/src/ares_private.h | 10 +- deps/cares/src/ares_process.c | 88 ++++++++++- deps/cares/src/ares_query.c | 2 +- deps/cares/src/ares_strsplit.h | 1 + 18 files changed, 386 insertions(+), 54 deletions(-) create mode 100644 deps/cares/src/ares_parse_caa_reply.c diff --git a/deps/cares/cares.gyp b/deps/cares/cares.gyp index 02b2774c02683e..0dc4ff9317745c 100644 --- a/deps/cares/cares.gyp +++ b/deps/cares/cares.gyp @@ -75,6 +75,7 @@ 'src/ares__parse_into_addrinfo.c', 'src/ares_parse_aaaa_reply.c', 'src/ares_parse_a_reply.c', + 'src/ares_parse_caa_reply.c', 'src/ares_parse_mx_reply.c', 'src/ares_parse_naptr_reply.c', 'src/ares_parse_ns_reply.c', diff --git a/deps/cares/include/ares.h b/deps/cares/include/ares.h index 91dc754dfb6a18..70a1baf7d71738 100644 --- a/deps/cares/include/ares.h +++ b/deps/cares/include/ares.h @@ -528,6 +528,15 @@ struct ares_addr6ttl { int ttl; }; +struct ares_caa_reply { + struct ares_caa_reply *next; + int critical; + unsigned char *property; + size_t plength; /* plength excludes null termination */ + unsigned char *value; + size_t length; /* length excludes null termination */ +}; + struct ares_srv_reply { struct ares_srv_reply *next; char *host; @@ -637,6 +646,10 @@ CARES_EXTERN int ares_parse_aaaa_reply(const unsigned char *abuf, struct ares_addr6ttl *addrttls, int *naddrttls); +CARES_EXTERN int ares_parse_caa_reply(const unsigned char* abuf, + int alen, + struct ares_caa_reply** caa_out); + CARES_EXTERN int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, diff --git a/deps/cares/include/ares_version.h b/deps/cares/include/ares_version.h index c041d574dee09e..0bee17dfe646b4 100644 --- a/deps/cares/include/ares_version.h +++ b/deps/cares/include/ares_version.h @@ -6,12 +6,12 @@ #define ARES_COPYRIGHT "2004 - 2020 Daniel Stenberg, ." #define ARES_VERSION_MAJOR 1 -#define ARES_VERSION_MINOR 16 +#define ARES_VERSION_MINOR 17 #define ARES_VERSION_PATCH 1 #define ARES_VERSION ((ARES_VERSION_MAJOR<<16)|\ (ARES_VERSION_MINOR<<8)|\ (ARES_VERSION_PATCH)) -#define ARES_VERSION_STR "1.16.1" +#define ARES_VERSION_STR "1.17.1" #if (ARES_VERSION >= 0x010700) # define CARES_HAVE_ARES_LIBRARY_INIT 1 diff --git a/deps/cares/include/nameser.h b/deps/cares/include/nameser.h index a0302fd39894e6..5c1acce215573c 100644 --- a/deps/cares/include/nameser.h +++ b/deps/cares/include/nameser.h @@ -88,6 +88,7 @@ typedef enum __ns_type { ns_t_maila = 254, /* Transfer mail agent records. */ ns_t_any = 255, /* Wildcard match. */ ns_t_zxfr = 256, /* BIND-specific, nonstandard. */ + ns_t_caa = 257, /* Certification Authority Authorization. */ ns_t_max = 65536 } ns_type; @@ -204,8 +205,14 @@ typedef enum __ns_rcode { #define T_AXFR ns_t_axfr #define T_MAILB ns_t_mailb #define T_MAILA ns_t_maila +#define T_CAA ns_t_caa #define T_ANY ns_t_any #endif /* HAVE_ARPA_NAMESER_COMPAT_H */ +/* Android's bionic arpa/nameser_compat.h, nor glibc versions prior to 2.25 have T_OPT defined */ +#ifndef T_OPT +# define T_OPT ns_t_opt +#endif + #endif /* ARES_NAMESER_H */ diff --git a/deps/cares/src/ares__readaddrinfo.c b/deps/cares/src/ares__readaddrinfo.c index dd3abe2e9f8778..2b5bb40c3dd017 100644 --- a/deps/cares/src/ares__readaddrinfo.c +++ b/deps/cares/src/ares__readaddrinfo.c @@ -163,6 +163,10 @@ int ares__readaddrinfo(FILE *fp, continue; } + /* Zero-out 'addr' struct, as there are members that we may not set, especially + * for ipv6. We don't want garbage data */ + memset(&addr, 0, sizeof(addr)); + /* * Convert address string to network address for the requested families. * Actual address family possible values are AF_INET and AF_INET6 only. @@ -179,7 +183,7 @@ int ares__readaddrinfo(FILE *fp, } node->ai_family = addr.sa.sa_family = AF_INET; - node->ai_addrlen = sizeof(sizeof(addr.sa4)); + node->ai_addrlen = sizeof(addr.sa4); node->ai_addr = ares_malloc(sizeof(addr.sa4)); if (!node->ai_addr) { @@ -200,7 +204,7 @@ int ares__readaddrinfo(FILE *fp, } node->ai_family = addr.sa.sa_family = AF_INET6; - node->ai_addrlen = sizeof(sizeof(addr.sa6)); + node->ai_addrlen = sizeof(addr.sa6); node->ai_addr = ares_malloc(sizeof(addr.sa6)); if (!node->ai_addr) { diff --git a/deps/cares/src/ares__sortaddrinfo.c b/deps/cares/src/ares__sortaddrinfo.c index 7a90270a2a6b92..0ad3a5bd98b9ae 100644 --- a/deps/cares/src/ares__sortaddrinfo.c +++ b/deps/cares/src/ares__sortaddrinfo.c @@ -85,11 +85,12 @@ struct addrinfo_sort_elem #define ARES_IN6_IS_ADDR_6BONE(a) \ (((a)->s6_addr[0] == 0x3f) && ((a)->s6_addr[1] == 0xfe)) + static int get_scope(const struct sockaddr *addr) { if (addr->sa_family == AF_INET6) { - const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; + const struct sockaddr_in6 *addr6 = CARES_INADDR_CAST(const struct sockaddr_in6 *, addr); if (IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr)) { return ARES_IPV6_ADDR_MC_SCOPE(&addr6->sin6_addr); @@ -114,7 +115,7 @@ static int get_scope(const struct sockaddr *addr) } else if (addr->sa_family == AF_INET) { - const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr; + const struct sockaddr_in *addr4 = CARES_INADDR_CAST(const struct sockaddr_in *, addr); unsigned long int na = ntohl(addr4->sin_addr.s_addr); if (ARES_IN_LOOPBACK(na) || /* 127.0.0.0/8 */ (na & 0xffff0000) == 0xa9fe0000) /* 169.254.0.0/16 */ @@ -149,7 +150,7 @@ static int get_label(const struct sockaddr *addr) } else if (addr->sa_family == AF_INET6) { - const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; + const struct sockaddr_in6 *addr6 = CARES_INADDR_CAST(const struct sockaddr_in6 *, addr); if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) { return 0; @@ -210,7 +211,7 @@ static int get_precedence(const struct sockaddr *addr) } else if (addr->sa_family == AF_INET6) { - const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; + const struct sockaddr_in6 *addr6 = CARES_INADDR_CAST(const struct sockaddr_in6 *, addr); if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) { return 50; @@ -353,10 +354,10 @@ static int rfc6724_compare(const void *ptr1, const void *ptr2) { const struct sockaddr_in6 *a1_src = &a1->src_addr.sa6; const struct sockaddr_in6 *a1_dst = - (const struct sockaddr_in6 *)a1->ai->ai_addr; + CARES_INADDR_CAST(const struct sockaddr_in6 *, a1->ai->ai_addr); const struct sockaddr_in6 *a2_src = &a2->src_addr.sa6; const struct sockaddr_in6 *a2_dst = - (const struct sockaddr_in6 *)a2->ai->ai_addr; + CARES_INADDR_CAST(const struct sockaddr_in6 *, a2->ai->ai_addr); prefixlen1 = common_prefix_len(&a1_src->sin6_addr, &a1_dst->sin6_addr); prefixlen2 = common_prefix_len(&a2_src->sin6_addr, &a2_dst->sin6_addr); if (prefixlen1 != prefixlen2) @@ -384,7 +385,7 @@ static int find_src_addr(ares_channel channel, const struct sockaddr *addr, struct sockaddr *src_addr) { - int sock; + ares_socket_t sock; int ret; ares_socklen_t len; @@ -402,7 +403,7 @@ static int find_src_addr(ares_channel channel, } sock = ares__open_socket(channel, addr->sa_family, SOCK_DGRAM, IPPROTO_UDP); - if (sock == -1) + if (sock == ARES_SOCKET_BAD) { if (errno == EAFNOSUPPORT) { @@ -426,7 +427,7 @@ static int find_src_addr(ares_channel channel, return 0; } - if (getsockname(sock, src_addr, &len) == -1) + if (getsockname(sock, src_addr, &len) != 0) { ares__close_socket(channel, sock); return -1; @@ -491,4 +492,4 @@ int ares__sortaddrinfo(ares_channel channel, struct ares_addrinfo_node *list_sen ares_free(elems); return ARES_SUCCESS; -} \ No newline at end of file +} diff --git a/deps/cares/src/ares_data.c b/deps/cares/src/ares_data.c index 18dd650c7b91fb..aa925b8b511b2e 100644 --- a/deps/cares/src/ares_data.c +++ b/deps/cares/src/ares_data.c @@ -119,6 +119,16 @@ void ares_free_data(void *dataptr) ares_free(ptr->data.soa_reply.hostmaster); break; + case ARES_DATATYPE_CAA_REPLY: + + if (ptr->data.caa_reply.next) + next_data = ptr->data.caa_reply.next; + if (ptr->data.caa_reply.property) + ares_free(ptr->data.caa_reply.property); + if (ptr->data.caa_reply.value) + ares_free(ptr->data.caa_reply.value); + break; + default: return; } @@ -174,6 +184,14 @@ void *ares_malloc_data(ares_datatype type) ptr->data.txt_reply.length = 0; break; + case ARES_DATATYPE_CAA_REPLY: + ptr->data.caa_reply.next = NULL; + ptr->data.caa_reply.plength = 0; + ptr->data.caa_reply.property = NULL; + ptr->data.caa_reply.length = 0; + ptr->data.caa_reply.value = NULL; + break; + case ARES_DATATYPE_ADDR_NODE: ptr->data.addr_node.next = NULL; ptr->data.addr_node.family = 0; diff --git a/deps/cares/src/ares_data.h b/deps/cares/src/ares_data.h index ffee2be6baab8a..b0182fd6907499 100644 --- a/deps/cares/src/ares_data.h +++ b/deps/cares/src/ares_data.h @@ -30,6 +30,7 @@ typedef enum { ARES_DATATYPE_OPTIONS, /* struct ares_options */ #endif ARES_DATATYPE_ADDR_PORT_NODE, /* struct ares_addr_port_node - introduced in 1.11.0 */ + ARES_DATATYPE_CAA_REPLY, /* struct ares_caa_reply - introduced in 1.17 */ ARES_DATATYPE_LAST /* not used - introduced in 1.7.0 */ } ares_datatype; @@ -65,6 +66,7 @@ struct ares_data { struct ares_mx_reply mx_reply; struct ares_naptr_reply naptr_reply; struct ares_soa_reply soa_reply; + struct ares_caa_reply caa_reply; } data; }; diff --git a/deps/cares/src/ares_getaddrinfo.c b/deps/cares/src/ares_getaddrinfo.c index be168068b1d424..ecd5dd5112cb51 100644 --- a/deps/cares/src/ares_getaddrinfo.c +++ b/deps/cares/src/ares_getaddrinfo.c @@ -386,6 +386,9 @@ static int fake_addrinfo(const char *name, } } + node->ai_socktype = hints->ai_socktype; + node->ai_protocol = hints->ai_protocol; + callback(arg, ARES_SUCCESS, 0, ai); return 1; } @@ -406,6 +409,8 @@ static void end_hquery(struct host_query *hquery, int status) /* Set port into each address (resolved separately). */ while (next) { + next->ai_socktype = hquery->hints.ai_socktype; + next->ai_protocol = hquery->hints.ai_protocol; if (next->ai_family == AF_INET) { (CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr))->sin_port = htons(hquery->port); @@ -754,6 +759,7 @@ static int as_is_first(const struct host_query* hquery) { char* p; int ndots = 0; + size_t nname = strlen(hquery->name); for (p = hquery->name; *p; p++) { if (*p == '.') @@ -761,5 +767,10 @@ static int as_is_first(const struct host_query* hquery) ndots++; } } + if (nname && hquery->name[nname-1] == '.') + { + /* prevent ARES_EBADNAME for valid FQDN, where ndots < channel->ndots */ + return 1; + } return ndots >= hquery->channel->ndots; } diff --git a/deps/cares/src/ares_gethostbyaddr.c b/deps/cares/src/ares_gethostbyaddr.c index a8ca0f5744d376..54eb5997392764 100644 --- a/deps/cares/src/ares_gethostbyaddr.c +++ b/deps/cares/src/ares_gethostbyaddr.c @@ -208,7 +208,6 @@ static int file_lookup(struct ares_addr *addr, struct hostent **host) strcat(PATH_HOSTS, WIN_PATH_HOSTS); #elif defined(WATT32) - extern const char *_w32_GetHostsFile (void); const char *PATH_HOSTS = _w32_GetHostsFile(); if (!PATH_HOSTS) diff --git a/deps/cares/src/ares_gethostbyname.c b/deps/cares/src/ares_gethostbyname.c index ecd03e79310c63..4e41898496fbf9 100644 --- a/deps/cares/src/ares_gethostbyname.c +++ b/deps/cares/src/ares_gethostbyname.c @@ -258,7 +258,7 @@ static int fake_hostent(const char *name, int family, struct in_addr in; struct ares_in6_addr in6; - if (family == AF_INET || family == AF_INET6) + if (family == AF_INET || family == AF_UNSPEC) { /* It only looks like an IP address if it's all numbers and dots. */ int numdots = 0, valid = 1; @@ -276,13 +276,17 @@ static int fake_hostent(const char *name, int family, /* if we don't have 3 dots, it is illegal * (although inet_pton doesn't think so). */ - if (numdots != 3 || !valid) + if (numdots != 3 || !valid) { result = 0; - else + } else { result = (ares_inet_pton(AF_INET, name, &in) < 1 ? 0 : 1); + } - if (result) - family = AF_INET; + /* + * Set address family in case of failure, + * as we will try to convert it later afterwards + */ + family = result ? AF_INET : AF_INET6; } if (family == AF_INET6) result = (ares_inet_pton(AF_INET6, name, &in6) < 1 ? 0 : 1); @@ -383,7 +387,6 @@ static int file_lookup(const char *name, int family, struct hostent **host) strcat(PATH_HOSTS, WIN_PATH_HOSTS); #elif defined(WATT32) - extern const char *_w32_GetHostsFile (void); const char *PATH_HOSTS = _w32_GetHostsFile(); if (!PATH_HOSTS) diff --git a/deps/cares/src/ares_init.c b/deps/cares/src/ares_init.c index dffa518171b29c..92187e463e69c9 100644 --- a/deps/cares/src/ares_init.c +++ b/deps/cares/src/ares_init.c @@ -115,20 +115,6 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options, int status = ARES_SUCCESS; struct timeval now; -#ifdef CURLDEBUG - const char *env = getenv("CARES_MEMDEBUG"); - - if (env) - curl_memdebug(env); - env = getenv("CARES_MEMLIMIT"); - if (env) { - char *endptr; - long num = strtol(env, &endptr, 10); - if((endptr != env) && (endptr == env + strlen(env)) && (num > 0)) - curl_memlimit(num); - } -#endif - if (ares_library_initialized() != ARES_SUCCESS) return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */ @@ -1611,7 +1597,8 @@ static int init_by_resolv_conf(ares_channel channel) if (channel->nservers == -1) { union res_sockaddr_union addr[MAXNS]; int nscount = res_getservers(&res, addr, MAXNS); - for (int i = 0; i < nscount; ++i) { + int i; + for (i = 0; i < nscount; ++i) { char str[INET6_ADDRSTRLEN]; int config_status; sa_family_t family = addr[i].sin.sin_family; @@ -1639,8 +1626,9 @@ static int init_by_resolv_conf(ares_channel channel) if (!channel->domains) { status = ARES_ENOMEM; } else { + int i; channel->ndomains = entries; - for (int i = 0; i < channel->ndomains; ++i) { + for (i = 0; i < channel->ndomains; ++i) { channel->domains[i] = ares_strdup(res.dnsrch[i]); if (!channel->domains[i]) status = ARES_ENOMEM; diff --git a/deps/cares/src/ares_parse_caa_reply.c b/deps/cares/src/ares_parse_caa_reply.c new file mode 100644 index 00000000000000..620f444e007900 --- /dev/null +++ b/deps/cares/src/ares_parse_caa_reply.c @@ -0,0 +1,209 @@ + +/* Copyright 2020 by + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif +#ifdef HAVE_ARPA_NAMESER_H +# include +#else +# include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +# include +#endif + +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "ares.h" +#include "ares_dns.h" +#include "ares_data.h" +#include "ares_private.h" + +#ifndef T_CAA +# define T_CAA 257 /* Certification Authority Authorization */ +#endif + +int +ares_parse_caa_reply (const unsigned char *abuf, int alen, + struct ares_caa_reply **caa_out) +{ + unsigned int qdcount, ancount, i; + const unsigned char *aptr; + const unsigned char *strptr; + int status, rr_type, rr_class, rr_len; + long len; + char *hostname = NULL, *rr_name = NULL; + struct ares_caa_reply *caa_head = NULL; + struct ares_caa_reply *caa_last = NULL; + struct ares_caa_reply *caa_curr; + + /* Set *caa_out to NULL for all failure cases. */ + *caa_out = NULL; + + /* Give up if abuf doesn't have room for a header. */ + if (alen < HFIXEDSZ) + return ARES_EBADRESP; + + /* Fetch the question and answer count from the header. */ + qdcount = DNS_HEADER_QDCOUNT (abuf); + ancount = DNS_HEADER_ANCOUNT (abuf); + if (qdcount != 1) + return ARES_EBADRESP; + if (ancount == 0) + return ARES_ENODATA; + + /* Expand the name from the question, and skip past the question. */ + aptr = abuf + HFIXEDSZ; + status = ares_expand_name (aptr, abuf, alen, &hostname, &len); + if (status != ARES_SUCCESS) + return status; + + if (aptr + len + QFIXEDSZ > abuf + alen) + { + ares_free (hostname); + return ARES_EBADRESP; + } + aptr += len + QFIXEDSZ; + + /* Examine each answer resource record (RR) in turn. */ + for (i = 0; i < ancount; i++) + { + /* Decode the RR up to the data field. */ + status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); + if (status != ARES_SUCCESS) + { + break; + } + aptr += len; + if (aptr + RRFIXEDSZ > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + rr_type = DNS_RR_TYPE (aptr); + rr_class = DNS_RR_CLASS (aptr); + rr_len = DNS_RR_LEN (aptr); + aptr += RRFIXEDSZ; + if (aptr + rr_len > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + + /* Check if we are really looking at a CAA record */ + if ((rr_class == C_IN || rr_class == C_CHAOS) && rr_type == T_CAA) + { + strptr = aptr; + + /* Allocate storage for this CAA answer appending it to the list */ + caa_curr = ares_malloc_data(ARES_DATATYPE_CAA_REPLY); + if (!caa_curr) + { + status = ARES_ENOMEM; + break; + } + if (caa_last) + { + caa_last->next = caa_curr; + } + else + { + caa_head = caa_curr; + } + caa_last = caa_curr; + if (rr_len < 2) + { + status = ARES_EBADRESP; + break; + } + caa_curr->critical = (int)*strptr++; + caa_curr->plength = (int)*strptr++; + if (caa_curr->plength <= 0 || (int)caa_curr->plength >= rr_len - 2) + { + status = ARES_EBADRESP; + break; + } + caa_curr->property = ares_malloc (caa_curr->plength + 1/* Including null byte */); + if (caa_curr->property == NULL) + { + status = ARES_ENOMEM; + break; + } + memcpy ((char *) caa_curr->property, strptr, caa_curr->plength); + /* Make sure we NULL-terminate */ + caa_curr->property[caa_curr->plength] = 0; + strptr += caa_curr->plength; + + caa_curr->length = rr_len - caa_curr->plength - 2; + if (caa_curr->length <= 0) + { + status = ARES_EBADRESP; + break; + } + caa_curr->value = ares_malloc (caa_curr->length + 1/* Including null byte */); + if (caa_curr->value == NULL) + { + status = ARES_ENOMEM; + break; + } + memcpy ((char *) caa_curr->value, strptr, caa_curr->length); + /* Make sure we NULL-terminate */ + caa_curr->value[caa_curr->length] = 0; + } + + /* Propagate any failures */ + if (status != ARES_SUCCESS) + { + break; + } + + /* Don't lose memory in the next iteration */ + ares_free (rr_name); + rr_name = NULL; + + /* Move on to the next record */ + aptr += rr_len; + } + + if (hostname) + ares_free (hostname); + if (rr_name) + ares_free (rr_name); + + /* clean up on error */ + if (status != ARES_SUCCESS) + { + if (caa_head) + ares_free_data (caa_head); + return status; + } + + /* everything looks fine, return the data */ + *caa_out = caa_head; + + return ARES_SUCCESS; +} diff --git a/deps/cares/src/ares_parse_soa_reply.c b/deps/cares/src/ares_parse_soa_reply.c index d72eeb94148e27..7cfaed2b33372a 100644 --- a/deps/cares/src/ares_parse_soa_reply.c +++ b/deps/cares/src/ares_parse_soa_reply.c @@ -62,13 +62,16 @@ ares_parse_soa_reply(const unsigned char *abuf, int alen, return ARES_EBADRESP; if (ancount == 0) return ARES_EBADRESP; - + aptr = abuf + HFIXEDSZ; /* query name */ status = ares__expand_name_for_response(aptr, abuf, alen, &qname, &len); if (status != ARES_SUCCESS) goto failed_stat; + + if (alen <= len + HFIXEDSZ + 1) + goto failed; aptr += len; qclass = DNS_QUESTION_TYPE(aptr); @@ -161,9 +164,9 @@ ares_parse_soa_reply(const unsigned char *abuf, int alen, return ARES_SUCCESS; } aptr += rr_len; - + ares_free(rr_name); - + if (aptr > abuf + alen) goto failed_stat; } diff --git a/deps/cares/src/ares_private.h b/deps/cares/src/ares_private.h index 1884c1659681c1..50b2ba06e15b38 100644 --- a/deps/cares/src/ares_private.h +++ b/deps/cares/src/ares_private.h @@ -74,6 +74,7 @@ #elif defined(WATT32) #define PATH_RESOLV_CONF "/dev/ENV/etc/resolv.conf" +W32_FUNC const char *_w32_GetHostsFile (void); #elif defined(NETWARE) @@ -415,13 +416,4 @@ int ares__connect_socket(ares_channel channel, (c)->sock_state_cb((c)->sock_state_cb_data, (s), (r), (w)); \ } WHILE_FALSE -#ifdef CURLDEBUG -/* This is low-level hard-hacking memory leak tracking and similar. Using the - libcurl lowlevel code from within library is ugly and only works when - c-ares is built and linked with a similarly curldebug-enabled libcurl, - but we do this anyway for convenience. */ -#define HEADER_CURL_SETUP_ONCE_H -#include "../lib/memdebug.h" -#endif - #endif /* __ARES_PRIVATE_H */ diff --git a/deps/cares/src/ares_process.c b/deps/cares/src/ares_process.c index ff71f66a1ecce0..65c1b7ff1a856c 100644 --- a/deps/cares/src/ares_process.c +++ b/deps/cares/src/ares_process.c @@ -34,13 +34,13 @@ #endif #ifdef HAVE_ARPA_NAMESER_H # include -#else -# include "nameser.h" #endif #ifdef HAVE_ARPA_NAMESER_COMPAT_H # include #endif +#include "nameser.h" + #ifdef HAVE_STRINGS_H # include #endif @@ -87,6 +87,7 @@ static int open_udp_socket(ares_channel channel, struct server_state *server); static int same_questions(const unsigned char *qbuf, int qlen, const unsigned char *abuf, int alen); static int same_address(struct sockaddr *sa, struct ares_addr *aa); +static int has_opt_rr(const unsigned char *abuf, int alen); static void end_query(ares_channel channel, struct query *query, int status, unsigned char *abuf, int alen); @@ -608,14 +609,14 @@ static void process_answer(ares_channel channel, unsigned char *abuf, return; packetsz = PACKETSZ; - /* If we use EDNS and server answers with one of these RCODES, the protocol + /* If we use EDNS and server answers with FORMERR without an OPT RR, the protocol * extension is not understood by the responder. We must retry the query * without EDNS enabled. */ if (channel->flags & ARES_FLAG_EDNS) { packetsz = channel->ednspsz; - if (rcode == NOTIMP || rcode == FORMERR || rcode == SERVFAIL) + if (rcode == FORMERR && has_opt_rr(abuf, alen) != 1) { int qlen = (query->tcplen - 2) - EDNSFIXEDSZ; channel->flags ^= ARES_FLAG_EDNS; @@ -1354,6 +1355,85 @@ static int same_address(struct sockaddr *sa, struct ares_addr *aa) return 0; /* different */ } +/* search for an OPT RR in the response */ +static int has_opt_rr(const unsigned char *abuf, int alen) +{ + unsigned int qdcount, ancount, nscount, arcount, i; + const unsigned char *aptr; + int status; + + if (alen < HFIXEDSZ) + return -1; + + /* Parse the answer header. */ + qdcount = DNS_HEADER_QDCOUNT(abuf); + ancount = DNS_HEADER_ANCOUNT(abuf); + nscount = DNS_HEADER_NSCOUNT(abuf); + arcount = DNS_HEADER_ARCOUNT(abuf); + + aptr = abuf + HFIXEDSZ; + + /* skip the questions */ + for (i = 0; i < qdcount; i++) + { + char* name; + long len; + status = ares_expand_name(aptr, abuf, alen, &name, &len); + if (status != ARES_SUCCESS) + return -1; + ares_free_string(name); + if (aptr + len + QFIXEDSZ > abuf + alen) + return -1; + aptr += len + QFIXEDSZ; + } + + /* skip the ancount and nscount */ + for (i = 0; i < ancount + nscount; i++) + { + char* name; + long len; + int dlen; + status = ares_expand_name(aptr, abuf, alen, &name, &len); + if (status != ARES_SUCCESS) + return -1; + ares_free_string(name); + if (aptr + len + RRFIXEDSZ > abuf + alen) + return -1; + aptr += len; + dlen = DNS_RR_LEN(aptr); + aptr += RRFIXEDSZ; + if (aptr + dlen > abuf + alen) + return -1; + aptr += dlen; + } + + /* search for rr type (41) - opt */ + for (i = 0; i < arcount; i++) + { + char* name; + long len; + int dlen; + status = ares_expand_name(aptr, abuf, alen, &name, &len); + if (status != ARES_SUCCESS) + return -1; + ares_free_string(name); + if (aptr + len + RRFIXEDSZ > abuf + alen) + return -1; + aptr += len; + + if (DNS_RR_TYPE(aptr) == T_OPT) + return 1; + + dlen = DNS_RR_LEN(aptr); + aptr += RRFIXEDSZ; + if (aptr + dlen > abuf + alen) + return -1; + aptr += dlen; + } + + return 0; +} + static void end_query (ares_channel channel, struct query *query, int status, unsigned char *abuf, int alen) { diff --git a/deps/cares/src/ares_query.c b/deps/cares/src/ares_query.c index b38b8a6c22c4db..5bbb2f5c326bdb 100644 --- a/deps/cares/src/ares_query.c +++ b/deps/cares/src/ares_query.c @@ -45,7 +45,7 @@ static void rc4(rc4_key* key, unsigned char *buffer_ptr, int buffer_len) unsigned char y; unsigned char* state; unsigned char xorIndex; - short counter; + int counter; x = key->x; y = key->y; diff --git a/deps/cares/src/ares_strsplit.h b/deps/cares/src/ares_strsplit.h index da286a9aef6b51..e00fd14dd5a131 100644 --- a/deps/cares/src/ares_strsplit.h +++ b/deps/cares/src/ares_strsplit.h @@ -40,3 +40,4 @@ void ares_strsplit_free(char **elms, size_t num_elm); #endif /* HEADER_CARES_STRSPLIT_H */ +