[git] GnuPG - branch, master, updated. gnupg-2.1.21-52-g15d2a00

by Justus Winter cvs at cvs.gnupg.org
Tue Jun 13 11:59:59 CEST 2017


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  15d2a009931f44a60b9df6325f837add208459d6 (commit)
      from  e80925171ddb20c7e76c1db88c15ce2d9b09db86 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 15d2a009931f44a60b9df6325f837add208459d6
Author: Justus Winter <justus at g10code.com>
Date:   Tue Jun 13 11:33:06 2017 +0200

    dirmngr: Implement querying nameservers over IPv6.
    
    * dirmngr/dns.c (dns_so_check): Reinitialize sockets on address family
    mismatch.
    (enum dns_res_state): New states for querying over IPv6.
    (dns_res_exec): Implement the new states by copying and modifying the
    IPv4 variants.  Branch to their respective counterparts if the current
    list of resolvers using the current address family is exhausted.
    --
    
    This allows dirmngr to resolve names on systems where the nameservers
    are only reachable via IPv6.
    
    GnuPG-bug-id: 2990
    Signed-off-by: Justus Winter <justus at g10code.com>

diff --git a/dirmngr/dns.c b/dirmngr/dns.c
index c660cf5..a89411b 100644
--- a/dirmngr/dns.c
+++ b/dirmngr/dns.c
@@ -7583,6 +7583,22 @@ int dns_so_check(struct dns_socket *so) {
 retry:
 	switch (so->state) {
 	case DNS_SO_UDP_INIT:
+		if (so->remote.ss_family != so->local.ss_family) {
+			/* Family mismatch.  Reinitialize.  */
+			if ((error = dns_so_closefd(so, &so->udp)))
+				goto error;
+			if ((error = dns_so_closefd(so, &so->tcp)))
+				goto error;
+
+			/* If the user supplied an interface
+			   statement, that is gone now.  Sorry.  */
+			memset(&so->local, 0, sizeof so->local);
+			so->local.ss_family = so->remote.ss_family;
+
+			if (-1 == (so->udp = dns_socket((struct sockaddr *)&so->local, SOCK_DGRAM, &error)))
+				goto error;
+		}
+
 		so->state++;
 	case DNS_SO_UDP_CONN:
 		error = dns_connect(so->udp, (struct sockaddr *)&so->remote, dns_sa_len(&so->remote));
@@ -7621,6 +7637,19 @@ retry:
 
 		so->state++;
 	case DNS_SO_TCP_INIT:
+		if (so->remote.ss_family != so->local.ss_family) {
+			/* Family mismatch.  Reinitialize.  */
+			if ((error = dns_so_closefd(so, &so->udp)))
+				goto error;
+			if ((error = dns_so_closefd(so, &so->tcp)))
+				goto error;
+
+			/* If the user supplied an interface
+			   statement, that is gone now.  Sorry.  */
+			memset(&so->local, 0, sizeof so->local);
+			so->local.ss_family = so->remote.ss_family;
+		}
+
 		if (dns_so_tcp_keep(so)) {
 			so->state = DNS_SO_TCP_SEND;
 
@@ -8072,6 +8101,8 @@ enum dns_res_state {
 	DNS_R_RESOLV1_NS,	/* Epilog: Inspect answer */
 	DNS_R_FOREACH_A,
 	DNS_R_QUERY_A,
+	DNS_R_FOREACH_AAAA,
+	DNS_R_QUERY_AAAA,
 	DNS_R_CNAME0_A,
 	DNS_R_CNAME1_A,
 
@@ -8731,8 +8762,22 @@ exec:
 		F->hints_j.section	= DNS_S_ALL & ~DNS_S_QD;
 
 		if (!dns_rr_grep(&rr, 1, &F->hints_j, F->hints, &error)) {
-			if (!dns_rr_i_count(&F->hints_j))
+			if (!dns_rr_i_count(&F->hints_j)) {
+				/* Check if we have in fact servers
+				   with an IPv6 address.  */
+				dns_rr_i_init(&F->hints_j, F->hints);
+				F->hints_j.name		= u.ns.host;
+				F->hints_j.type		= DNS_T_AAAA;
+				F->hints_j.section	= DNS_S_ALL & ~DNS_S_QD;
+				if (dns_rr_grep(&rr, 1, &F->hints_j, F->hints, &error)) {
+					/* We do.  Reinitialize
+					   iterator and handle it.  */
+					dns_rr_i_init(&F->hints_j, F->hints);
+					dgoto(R->sp, DNS_R_FOREACH_AAAA);
+				}
+
 				dgoto(R->sp, DNS_R_RESOLV0_NS);
+			}
 
 			dgoto(R->sp, DNS_R_FOREACH_NS);
 		}
@@ -8833,6 +8878,139 @@ exec:
 		/* XXX: Should we copy F->answer to R->nodata? */
 
 		dgoto(R->sp, DNS_R_FOREACH_A);
+	case DNS_R_FOREACH_AAAA: {
+		struct dns_aaaa aaaa;
+		struct sockaddr_in6 sin6;
+
+		/*
+		 * NOTE: Iterator initialized in DNS_R_FOREACH_NS because
+		 * this state is re-entrant, but we need to reset
+		 * .name to a valid pointer each time.
+		 */
+		if ((error = dns_ns_parse(&u.ns, &F->hints_ns, F->hints)))
+			goto error;
+
+		F->hints_j.name		= u.ns.host;
+		F->hints_j.type		= DNS_T_AAAA;
+		F->hints_j.section	= DNS_S_ALL & ~DNS_S_QD;
+
+		if (!dns_rr_grep(&rr, 1, &F->hints_j, F->hints, &error)) {
+			if (!dns_rr_i_count(&F->hints_j)) {
+				/* Check if we have in fact servers
+				   with an IPv4 address.  */
+				dns_rr_i_init(&F->hints_j, F->hints);
+				F->hints_j.name		= u.ns.host;
+				F->hints_j.type		= DNS_T_A;
+				F->hints_j.section	= DNS_S_ALL & ~DNS_S_QD;
+				if (dns_rr_grep(&rr, 1, &F->hints_j, F->hints, &error)) {
+					/* We do.  Reinitialize
+					   iterator and handle it.  */
+					dns_rr_i_init(&F->hints_j, F->hints);
+					dgoto(R->sp, DNS_R_FOREACH_A);
+				}
+
+				dgoto(R->sp, DNS_R_RESOLV0_NS);
+			}
+
+			dgoto(R->sp, DNS_R_FOREACH_NS);
+		}
+
+		if ((error = dns_aaaa_parse(&aaaa, &rr, F->hints)))
+			goto error;
+
+		memset(&sin6, '\0', sizeof sin6); /* NB: silence valgrind */
+		sin6.sin6_family	= AF_INET6;
+		sin6.sin6_addr	= aaaa.addr;
+		if (R->sp == 0)
+			sin6.sin6_port = dns_hints_port(R->hints, AF_INET, &sin6.sin6_addr);
+		else
+			sin6.sin6_port = htons(53);
+
+		if (DNS_DEBUG) {
+			char addr[INET6_ADDRSTRLEN + 1];
+			dns_aaaa_print(addr, sizeof addr, &aaaa);
+			dns_header(F->query)->qid = dns_so_mkqid(&R->so);
+			DNS_SHOW(F->query, "ASKING: %s/%s @ DEPTH: %u)", u.ns.host, addr, R->sp);
+		}
+
+		dns_trace_setcname(R->trace, u.ns.host, (struct sockaddr *)&sin6);
+
+		if ((error = dns_so_submit(&R->so, F->query, (struct sockaddr *)&sin6)))
+			goto error;
+
+		F->state++;
+	}
+	case DNS_R_QUERY_AAAA:
+		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)))
+			goto error;
+
+		if (!dns_p_setptr(&F->answer, dns_so_fetch(&R->so, &error)))
+			goto error;
+
+		if (DNS_DEBUG) {
+			DNS_SHOW(F->answer, "ANSWER @ DEPTH: %u)", R->sp);
+		}
+
+		if (dns_p_rcode(F->answer) == DNS_RC_FORMERR ||
+		    dns_p_rcode(F->answer) == DNS_RC_NOTIMP ||
+		    dns_p_rcode(F->answer) == DNS_RC_BADVERS) {
+			/* Temporarily disable EDNS0 and try again. */
+			if (F->qflags & DNS_Q_EDNS0) {
+				F->qflags &= ~DNS_Q_EDNS0;
+				if ((error = dns_q_remake(&F->query, F->qflags)))
+					goto error;
+
+				dgoto(R->sp, DNS_R_FOREACH_AAAA);
+			}
+		}
+
+		if ((error = dns_rr_parse(&rr, 12, F->query)))
+			goto error;
+
+		if (!(len = dns_d_expand(u.name, sizeof u.name, rr.dn.p, F->query, &error)))
+			goto error;
+		else if (len >= sizeof u.name)
+			goto toolong;
+
+		dns_rr_foreach(&rr, F->answer, .section = DNS_S_AN, .name = u.name, .type = rr.type) {
+			dgoto(R->sp, DNS_R_FINISH);	/* Found */
+		}
+
+		dns_rr_foreach(&rr, F->answer, .section = DNS_S_AN, .name = u.name, .type = DNS_T_CNAME) {
+			F->ans_cname	= rr;
+
+			dgoto(R->sp, DNS_R_CNAME0_A);
+		}
+
+		/*
+		 * XXX: The condition here should probably check whether
+		 * R->sp == 0, because DNS_R_SEARCH runs regardless of
+		 * options.recurse. See DNS_R_BIND.
+		 */
+		if (!R->resconf->options.recurse) {
+			/* Make first answer our tentative answer */
+			if (!R->nodata)
+				dns_p_movptr(&R->nodata, &F->answer);
+
+			dgoto(R->sp, DNS_R_SEARCH);
+		}
+
+		dns_rr_foreach(&rr, F->answer, .section = DNS_S_NS, .type = DNS_T_NS) {
+			dns_p_movptr(&F->hints, &F->answer);
+
+			dgoto(R->sp, DNS_R_ITERATE);
+		}
+
+		/* XXX: Should this go further up? */
+		if (dns_header(F->answer)->aa)
+			dgoto(R->sp, DNS_R_FINISH);
+
+		/* XXX: Should we copy F->answer to R->nodata? */
+
+		dgoto(R->sp, DNS_R_FOREACH_AAAA);
 	case DNS_R_CNAME0_A:
 		if (&F[1] >= endof(R->stack))
 			dgoto(R->sp, DNS_R_FINISH);

-----------------------------------------------------------------------

Summary of changes:
 dirmngr/dns.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 179 insertions(+), 1 deletion(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list