From 3e6ad302eaf3a4a9f3e60379133b3dfdbe0e1b2d Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 14 Jun 2018 13:10:57 +0900 Subject: libdns: Sync to upstream. * dirmngr/dns.c (dns_nssconf_loadfile): Handle exclamation mark. -- Reverting local change, merge upstream's debug-tracing branch. (commit 21281fc1b63bb74d51762b8e363c49b1a258783d) Fixes-commit: d4c0187dd93163f12e9f953366adef81ecf526a6 Signed-off-by: NIIBE Yutaka --- dirmngr/dns.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'dirmngr/dns.c') diff --git a/dirmngr/dns.c b/dirmngr/dns.c index 8e8b6db0b..13ef4b8fd 100644 --- a/dirmngr/dns.c +++ b/dirmngr/dns.c @@ -6096,17 +6096,9 @@ int dns_nssconf_loadfile(struct dns_resolv_conf *resconf, FILE *fp) { dns_anyconf_skip(" \t", fp); if ('[' == dns_anyconf_peek(fp)) { - dns_anyconf_skip("[ \t", fp); + dns_anyconf_skip("[! \t", fp); - for (;;) { - if ('!' == dns_anyconf_peek(fp)) { - dns_anyconf_skip("! \t", fp); - /* FIXME: negating statuses; currently not implemented */ - dns_anyconf_skip("^#;]\n", fp); /* skip to end of criteria */ - break; - } - - if (!dns_anyconf_scan(&cf, "%w_", fp, &error)) break; + while (dns_anyconf_scan(&cf, "%w_", fp, &error)) { dns_anyconf_skip("= \t", fp); if (!dns_anyconf_scan(&cf, "%w_", fp, &error)) { dns_anyconf_pop(&cf); /* discard status */ -- cgit v1.2.3 From 1c0b6681e4f322b88ac35d1f21c03d3cfc35fc23 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 15 Jun 2018 10:38:22 +0900 Subject: libdns: Clear struct sockaddr_storage by zero. * dirmngr/dns.c (dns_resconf_pton): Clear SS. (dns_resconf_setiface): Clear ->IFACE. (dns_hints_root, send_query): Clear SS. -- POSIX requires clear the structure of struct sockaddr_in6. On macOS, in some case like bind, it is better to clear even for struct sockaddr_in. Signed-off-by: NIIBE Yutaka --- dirmngr/dns.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'dirmngr/dns.c') diff --git a/dirmngr/dns.c b/dirmngr/dns.c index 13ef4b8fd..178070a90 100644 --- a/dirmngr/dns.c +++ b/dirmngr/dns.c @@ -5549,6 +5549,7 @@ int dns_resconf_pton(struct sockaddr_storage *ss, const char *src) { unsigned short port = 0; int ch, af = AF_INET, error; + memset(ss, 0, sizeof *ss); while ((ch = *src++)) { switch (ch) { case ' ': @@ -6311,6 +6312,7 @@ int dns_resconf_setiface(struct dns_resolv_conf *resconf, const char *addr, unsi int af = (strchr(addr, ':'))? AF_INET6 : AF_INET; int error; + memset(&resconf->iface, 0, sizeof (struct sockaddr_storage)); if ((error = dns_pton(af, addr, dns_sa_addr(af, &resconf->iface, NULL)))) return error; @@ -6622,6 +6624,7 @@ struct dns_hints *dns_hints_root(struct dns_resolv_conf *resconf, int *error_) { for (i = 0; i < lengthof(root_hints); i++) { af = root_hints[i].af; + memset(&ss, 0, sizeof ss); if ((error = dns_pton(af, root_hints[i].addr, dns_sa_addr(af, &ss, NULL)))) goto error; @@ -10866,6 +10869,7 @@ static int send_query(int argc, char *argv[]) { struct dns_socket *so; int error, type; + memset(&ss, 0, sizeof ss); if (argc > 1) { ss.ss_family = (strchr(argv[1], ':'))? AF_INET6 : AF_INET; -- cgit v1.2.3 From bcdbf8b8ebe9d61160e0b007dabe1b6462ffbc93 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 15 Jun 2018 12:58:29 +0900 Subject: libdns: Fix connect and try next nameserver when ECONNREFUSED. * dirmngr/dns.c (dns_so_check): When EINVAL, release the association by connect with AF_UNSPEC and try again. Also try again for ECONNREFUSED. (dns_res_exec): Try next nameserver when ECONNREFUSED. -- GnuPG-bug-id: T3374 Signed-off-by: NIIBE Yutaka --- dirmngr/dns.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'dirmngr/dns.c') diff --git a/dirmngr/dns.c b/dirmngr/dns.c index 178070a90..d2445a0c6 100644 --- a/dirmngr/dns.c +++ b/dirmngr/dns.c @@ -7614,8 +7614,23 @@ retry: so->state++; /* FALL THROUGH */ case DNS_SO_UDP_CONN: + udp_connect_retry: error = dns_connect(so->udp, (struct sockaddr *)&so->remote, dns_sa_len(&so->remote)); dns_trace_sys_connect(so->trace, so->udp, SOCK_DGRAM, (struct sockaddr *)&so->remote, error); + + /* Linux returns EINVAL when address was bound to + localhost and it's external IP address now. */ + if (error == EINVAL) { + struct sockaddr unspec_addr; + memset (&unspec_addr, 0, sizeof unspec_addr); + unspec_addr.sa_family = AF_UNSPEC; + connect(so->udp, &unspec_addr, sizeof unspec_addr); + goto udp_connect_retry; + } else if (error == ECONNREFUSED) + /* Error for previous socket operation may + be reserverd asynchronously. */ + goto udp_connect_retry; + if (error) goto error; @@ -8824,7 +8839,10 @@ exec: if (dns_so_elapsed(&R->so) >= dns_resconf_timeout(R->resconf)) dgoto(R->sp, DNS_R_FOREACH_A); - if ((error = dns_so_check(&R->so))) + error = dns_so_check(&R->so); + if (error == ECONNREFUSED) + dgoto(R->sp, DNS_R_FOREACH_A); + else if (error) goto error; if (!dns_p_setptr(&F->answer, dns_so_fetch(&R->so, &error))) @@ -8957,7 +8975,10 @@ exec: if (dns_so_elapsed(&R->so) >= dns_resconf_timeout(R->resconf)) dgoto(R->sp, DNS_R_FOREACH_AAAA); - if ((error = dns_so_check(&R->so))) + error = dns_so_check(&R->so); + if (error == ECONNREFUSED) + dgoto(R->sp, DNS_R_FOREACH_AAAA); + else if (error) goto error; if (!dns_p_setptr(&F->answer, dns_so_fetch(&R->so, &error))) -- cgit v1.2.3 From a4a054bf14fa855715faee01a152755c4e2a74f7 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 18 Jun 2018 10:13:35 +0900 Subject: libdns: Fix for non-FQDN hostname. * dirmngr/dns.c (dns_resconf_open): Clear search[0] for non-FQDN hostname. -- GnuPG-bug-id: T3803 Signed-off-by: NIIBE Yutaka --- dirmngr/dns.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'dirmngr/dns.c') diff --git a/dirmngr/dns.c b/dirmngr/dns.c index d2445a0c6..908bf157a 100644 --- a/dirmngr/dns.c +++ b/dirmngr/dns.c @@ -5371,13 +5371,16 @@ struct dns_resolv_conf *dns_resconf_open(int *error) { if (0 != gethostname(resconf->search[0], sizeof resconf->search[0])) goto syerr; - dns_d_anchor(resconf->search[0], sizeof resconf->search[0], resconf->search[0], strlen(resconf->search[0])); - dns_d_cleave(resconf->search[0], sizeof resconf->search[0], resconf->search[0], strlen(resconf->search[0])); - /* - * XXX: If gethostname() returned a string without any label - * separator, then search[0][0] should be NUL. + * If gethostname() returned a string without any label + * separator, then search[0][0] should be NUL. */ + if (strchr (resconf->search[0], '.')) { + dns_d_anchor(resconf->search[0], sizeof resconf->search[0], resconf->search[0], strlen(resconf->search[0])); + dns_d_cleave(resconf->search[0], sizeof resconf->search[0], resconf->search[0], strlen(resconf->search[0])); + } else { + memset (resconf->search[0], 0, sizeof resconf->search[0]); + } dns_resconf_acquire(resconf); -- cgit v1.2.3 From 861f1da0731bf29dcb9221c4f22c76b40ec15a78 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 20 Jun 2018 08:59:05 +0900 Subject: libdns: Let kernel to decide the local port. * dirmngr/dns.c (LEAVE_SELECTION_OF_PORT_TO_KERNEL): New. (dns_socket): Don't select ephemeral port in user space. -- There is no good reason to bind local port aggressively. It might be some reason to do so, then, a user can specify it in /etc/resolv.conf by the second argument of "interface" directive. At least, it causes a problem on Windows. Binding a specified port in user space can trigger the Firewall dialog on Windows. Since it can be considered valid question, it is better not to bind with an ephemeral port which is selected in user space, by default. GnuPG-bug-id: 3610 Signed-off-by: NIIBE Yutaka --- dirmngr/dns.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'dirmngr/dns.c') diff --git a/dirmngr/dns.c b/dirmngr/dns.c index 908bf157a..f82ed26cf 100644 --- a/dirmngr/dns.c +++ b/dirmngr/dns.c @@ -7121,6 +7121,8 @@ static int dns_socket(struct sockaddr *local, int type, int *error_) { if (type != SOCK_DGRAM) return fd; +#define LEAVE_SELECTION_OF_PORT_TO_KERNEL +#if !defined(LEAVE_SELECTION_OF_PORT_TO_KERNEL) /* * FreeBSD, Linux, OpenBSD, OS X, and Solaris use random ports by * default. Though the ephemeral range is quite small on OS X @@ -7146,6 +7148,7 @@ static int dns_socket(struct sockaddr *local, int type, int *error_) { /* NB: continue to next bind statement */ } +#endif if (0 == bind(fd, local, dns_sa_len(local))) return fd; -- cgit v1.2.3 From 1aacd12471935a354cfd85ee1805edc7eb16e6c5 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 2 Jul 2018 10:37:49 +0900 Subject: libdns: For SOCKS connection, just fails. * dirmngr/dns.c (dns_res_exec): If it's DNS_SO_SOCKS_CONN, don't iterate to other server, but return the error immediately. -- In the function libdns_switch_port_p in dns-stuff.c, this patch allows to fallback using TOR_PORT2 correctly. Fixes-commit: bcdbf8b8ebe9d61160e0b007dabe1b6462ffbc93 Signed-off-by: NIIBE Yutaka --- dirmngr/dns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'dirmngr/dns.c') diff --git a/dirmngr/dns.c b/dirmngr/dns.c index f82ed26cf..77f83f437 100644 --- a/dirmngr/dns.c +++ b/dirmngr/dns.c @@ -8846,7 +8846,7 @@ exec: dgoto(R->sp, DNS_R_FOREACH_A); error = dns_so_check(&R->so); - if (error == ECONNREFUSED) + if (R->so.state != DNS_SO_SOCKS_CONN && error == ECONNREFUSED) dgoto(R->sp, DNS_R_FOREACH_A); else if (error) goto error; -- cgit v1.2.3