[git] GnuPG - branch, master, updated. gnupg-2.1.17-77-ge6aebfe

by Werner Koch cvs at cvs.gnupg.org
Mon Jan 16 19:14:58 CET 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  e6aebfe3d0f16c483296fd125b66a44017fe15f4 (commit)
       via  9850124c7bdf0a0e7c1866abc85f3437257d7095 (commit)
       via  daae97bc14742c75408c4eb05808a2102cfe2bcf (commit)
       via  82646bbf1a5a7d745da81b239a12667a51703dc1 (commit)
      from  8b1611a9605b636db3e07a9d81016a11b318724c (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 e6aebfe3d0f16c483296fd125b66a44017fe15f4
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Jan 16 19:04:58 2017 +0100

    dirmngr: Implement hkps lookups using literal addresses.
    
    * dirmngr/ks-engine-hkp.c (map_host): For literal addresses do a
    reverse lookup.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
index 8c171a5..08ef851 100644
--- a/dirmngr/ks-engine-hkp.c
+++ b/dirmngr/ks-engine-hkp.c
@@ -85,7 +85,7 @@ struct hostinfo_s
   time_t died_at;    /* The time the host was marked dead.  If this is
                         0 the host has been manually marked dead.  */
   char *cname;       /* Canonical name of the host.  Only set if this
-                        is a pool.  */
+                        is a pool or NAME has a numerical IP address.  */
   char *v4addr;      /* A string with the v4 IP address of the host.
                         NULL if NAME has a numeric IP address or no v4
                         address is available.  */
@@ -571,6 +571,34 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
       hi = hosttable[hi->poolidx];
       assert (hi);
     }
+  else if (r_httphost && is_ip_address (hi->name))
+    {
+      /* This is a numerical IP address and not a pool.  We want to
+       * find the canonical name so that it can be used in the HTTP
+       * Host header.  Fixme: We should store that name in the
+       * hosttable. */
+      dns_addrinfo_t aibuf, ai;
+      char *host;
+
+      err = resolve_dns_name (hi->name, 0, 0, SOCK_STREAM, &aibuf, NULL);
+      if (!err)
+        {
+          for (ai = aibuf; ai; ai = ai->next)
+            {
+              if (ai->family == AF_INET6 || ai->family == AF_INET)
+                {
+                  err = resolve_dns_addr (ai->addr, ai->addrlen, 0, &host);
+                  if (!err)
+                    {
+                      /* Okay, we return the first found name.  */
+                      *r_httphost = host;
+                      break;
+                    }
+                }
+            }
+        }
+      free_dns_addrinfo (aibuf);
+    }
 
   if (hi->dead)
     {

commit 9850124c7bdf0a0e7c1866abc85f3437257d7095
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Jan 16 19:03:39 2017 +0100

    dirmngr: Allow reverse DNS lookups in Tor-mode.
    
    * dirmngr/dns-stuff.c (resolve_dns_name): Move up in the file.
    (resolve_addr_libdns): New.
    (resolve_dns_addr): Divert to resolve_dns_addr.
    --
    
    In the old code reverse lookups where disabled in Tor mode.  By
    implementing the reverse lookups via libdns it is now possible to do
    them also in Tor mode.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c
index 2debdca..28ecb18 100644
--- a/dirmngr/dns-stuff.c
+++ b/dirmngr/dns-stuff.c
@@ -892,6 +892,177 @@ resolve_name_standard (const char *name, unsigned short port,
 }
 
 
+/* This a wrapper around getaddrinfo with slightly different semantics.
+   NAME is the name to resolve.
+   PORT is the requested port or 0.
+   WANT_FAMILY is either 0 (AF_UNSPEC), AF_INET6, or AF_INET4.
+   WANT_SOCKETTYPE is either SOCK_STREAM or SOCK_DGRAM.
+
+   On success the result is stored in a linked list with the head
+   stored at the address R_AI; the caller must call gpg_addrinfo_free
+   on this.  If R_CANONNAME is not NULL the official name of the host
+   is stored there as a malloced string; if that name is not available
+   NULL is stored.  */
+gpg_error_t
+resolve_dns_name (const char *name, unsigned short port,
+                  int want_family, int want_socktype,
+                  dns_addrinfo_t *r_ai, char **r_canonname)
+{
+  gpg_error_t err;
+
+#ifdef USE_LIBDNS
+  if (!standard_resolver)
+    {
+      err = resolve_name_libdns (name, port, want_family, want_socktype,
+                                  r_ai, r_canonname);
+      if (err && libdns_switch_port_p (err))
+        err = resolve_name_libdns (name, port, want_family, want_socktype,
+                                   r_ai, r_canonname);
+    }
+  else
+#endif /*USE_LIBDNS*/
+    err = resolve_name_standard (name, port, want_family, want_socktype,
+                                 r_ai, r_canonname);
+  if (opt_debug)
+    log_debug ("dns: resolve_dns_name(%s): %s\n", name, gpg_strerror (err));
+  return err;
+}
+
+
+#ifdef USE_LIBDNS
+/* Resolve an address using libdns.  */
+static gpg_error_t
+resolve_addr_libdns (const struct sockaddr *addr, int addrlen,
+                     unsigned int flags, char **r_name)
+{
+  gpg_error_t err;
+  char host[DNS_D_MAXNAME + 1];
+  struct dns_resolver *res;
+  struct dns_packet *ans = NULL;
+  struct dns_ptr ptr;
+  int derr;
+
+  *r_name = NULL;
+
+  /* First we turn ADDR into a DNS name (with ".arpa" suffix).  */
+  err = 0;
+  if (addr->sa_family == AF_INET6)
+    {
+      const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)addr;
+      if (!dns_aaaa_arpa (host, sizeof host, (void*)&a6->sin6_addr))
+        err = gpg_error (GPG_ERR_INV_OBJ);
+    }
+  else if (addr->sa_family == AF_INET)
+    {
+      const struct sockaddr_in *a4 = (const struct sockaddr_in *)addr;
+      if (!dns_a_arpa (host, sizeof host, (void*)&a4->sin_addr))
+        err = gpg_error (GPG_ERR_INV_OBJ);
+    }
+  else
+    err = gpg_error (GPG_ERR_EAFNOSUPPORT);
+  if (err)
+    goto leave;
+
+
+  err = libdns_res_open (&res);
+  if (err)
+    goto leave;
+
+  err = libdns_res_submit (res, host, DNS_T_PTR, DNS_C_IN);
+  if (err)
+    goto leave;
+
+  err = libdns_res_wait (res);
+  if (err)
+    goto leave;
+
+  ans = dns_res_fetch (res, &derr);
+  if (!ans)
+    {
+      err = libdns_error_to_gpg_error (derr);
+      goto leave;
+    }
+
+  /* Check the rcode.  */
+  switch (dns_p_rcode (ans))
+    {
+    case DNS_RC_NOERROR:
+      break;
+    case DNS_RC_NXDOMAIN:
+      err = gpg_error (GPG_ERR_NO_NAME);
+      break;
+    default:
+      err = GPG_ERR_SERVER_FAILED;
+      goto leave;
+    }
+
+  /* Parse the result.  */
+  if (!err)
+    {
+      struct dns_rr rr;
+      struct dns_rr_i rri;
+
+      memset (&rri, 0, sizeof rri);
+      dns_rr_i_init (&rri, ans);
+      rri.section = DNS_S_ALL & ~DNS_S_QD;
+      rri.name    = host;
+      rri.type    = DNS_T_PTR;
+
+      if (!dns_rr_grep (&rr, 1, &rri, ans, &derr))
+        {
+          err = gpg_error (GPG_ERR_NOT_FOUND);
+          goto leave;
+        }
+
+      err = libdns_error_to_gpg_error (dns_ptr_parse (&ptr, &rr, ans));
+      if (err)
+        goto leave;
+
+      /* Copy result.  */
+      *r_name = xtrystrdup (ptr.host);
+      if (!*r_name)
+        {
+          err = gpg_error_from_syserror ();
+          goto leave;
+        }
+      /* Libdns appends the root zone part which is problematic
+       * for most other functions - strip it.  */
+      if (**r_name && (*r_name)[strlen (*r_name)-1] == '.')
+        (*r_name)[strlen (*r_name)-1] = 0;
+    }
+  else /* GPG_ERR_NO_NAME */
+    {
+      char *buffer, *p;
+      int buflen;
+      int ec;
+
+      buffer = ptr.host;
+      buflen = sizeof ptr.host;
+
+      p = buffer;
+      if (addr->sa_family == AF_INET6 && (flags & DNS_WITHBRACKET))
+        {
+          *p++ = '[';
+          buflen -= 2;
+        }
+      ec = getnameinfo (addr, addrlen, p, buflen, NULL, 0, NI_NUMERICHOST);
+      if (ec)
+        {
+          err = map_eai_to_gpg_error (ec);
+          goto leave;
+        }
+      if (addr->sa_family == AF_INET6 && (flags & DNS_WITHBRACKET))
+        strcat (buffer, "]");
+    }
+
+ leave:
+  dns_free (ans);
+  dns_res_close (res);
+  return err;
+}
+#endif /*USE_LIBDNS*/
+
+
 /* Resolve an address using the standard system function.  */
 static gpg_error_t
 resolve_addr_standard (const struct sockaddr *addr, int addrlen,
@@ -952,51 +1123,31 @@ resolve_addr_standard (const struct sockaddr *addr, int addrlen,
 }
 
 
-/* This a wrapper around getaddrinfo with slightly different semantics.
-   NAME is the name to resolve.
-   PORT is the requested port or 0.
-   WANT_FAMILY is either 0 (AF_UNSPEC), AF_INET6, or AF_INET4.
-   WANT_SOCKETTYPE is either SOCK_STREAM or SOCK_DGRAM.
-
-   On success the result is stored in a linked list with the head
-   stored at the address R_AI; the caller must call gpg_addrinfo_free
-   on this.  If R_CANONNAME is not NULL the official name of the host
-   is stored there as a malloced string; if that name is not available
-   NULL is stored.  */
+/* A wrapper around getnameinfo.  */
 gpg_error_t
-resolve_dns_name (const char *name, unsigned short port,
-                  int want_family, int want_socktype,
-                  dns_addrinfo_t *r_ai, char **r_canonname)
+resolve_dns_addr (const struct sockaddr *addr, int addrlen,
+                  unsigned int flags, char **r_name)
 {
   gpg_error_t err;
 
 #ifdef USE_LIBDNS
-  if (!standard_resolver)
+  /* Note that we divert to the standard resolver for NUMERICHOST.  */
+  if (!standard_resolver && !(flags & DNS_NUMERICHOST))
     {
-      err = resolve_name_libdns (name, port, want_family, want_socktype,
-                                  r_ai, r_canonname);
+      err = resolve_addr_libdns (addr, addrlen, flags, r_name);
       if (err && libdns_switch_port_p (err))
-        err = resolve_name_libdns (name, port, want_family, want_socktype,
-                                   r_ai, r_canonname);
+        err = resolve_addr_libdns (addr, addrlen, flags, r_name);
     }
   else
 #endif /*USE_LIBDNS*/
-    err = resolve_name_standard (name, port, want_family, want_socktype,
-                                 r_ai, r_canonname);
+    err = resolve_addr_standard (addr, addrlen, flags, r_name);
+
   if (opt_debug)
-    log_debug ("dns: resolve_dns_name(%s): %s\n", name, gpg_strerror (err));
+    log_debug ("dns: resolve_dns_addr(): %s\n", gpg_strerror (err));
   return err;
 }
 
 
-gpg_error_t
-resolve_dns_addr (const struct sockaddr *addr, int addrlen,
-                  unsigned int flags, char **r_name)
-{
-  return resolve_addr_standard (addr, addrlen, flags, r_name);
-}
-
-
 /* Check whether NAME is an IP address.  Returns a true if it is
  * either an IPv6 or a IPv4 numerical address.  The actual return
  * values can also be used to identify whether it is v4 or v6: The
@@ -1096,7 +1247,7 @@ get_dns_cert_libdns (const char *name, int want_certtype,
   int derr;
   int qtype;
 
-  /* Gte the query type from WANT_CERTTYPE (which in general indicates
+  /* Get the query type from WANT_CERTTYPE (which in general indicates
    * the subtype we want). */
   qtype = (want_certtype < DNS_CERTTYPE_RRBASE
            ? T_CERT

commit daae97bc14742c75408c4eb05808a2102cfe2bcf
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Jan 16 09:10:46 2017 +0100

    dirmngr: Avoid network queries for literal IP addresses.
    
    * dirmngr/dns-stuff.c (resolve_name_libdns): USe flags AI_NUMERICHOST
    for literal IP addresses.
    (resolve_name_standard): Ditto.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c
index 1b30c2c..2debdca 100644
--- a/dirmngr/dns-stuff.c
+++ b/dirmngr/dns-stuff.c
@@ -685,6 +685,8 @@ resolve_name_libdns (const char *name, unsigned short port,
   hints.ai_flags = AI_ADDRCONFIG;
   if (r_canonname)
     hints.ai_flags |= AI_CANONNAME;
+  if (is_ip_address (name))
+    hints.ai_flags |= AI_NUMERICHOST;
 
   if (port)
     {
@@ -806,6 +808,8 @@ resolve_name_standard (const char *name, unsigned short port,
   hints.ai_flags = AI_ADDRCONFIG;
   if (r_canonname)
     hints.ai_flags |= AI_CANONNAME;
+  if (is_ip_address (name))
+    hints.ai_flags |= AI_NUMERICHOST;
 
   if (port)
     snprintf (portstr, sizeof portstr, "%hu", port);

commit 82646bbf1a5a7d745da81b239a12667a51703dc1
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Jan 12 21:09:42 2017 +0100

    dirmngr: Fix URL creation for literal IPv6 addresses in HKP.
    
    * dirmngr/dns-stuff.c (is_ip_address): Make the return value depend on
    the address family.
    * dirmngr/ks-engine-hkp.c (map_host): Rename arg R_POOLNAME to
    R_HTTPHOST because that is its purpose.  Note that the former
    behaviour of storing a NULL to indicate that it is not a pool has not
    been used.
    (make_host_part): Ditto.
    (make_host_part): Make sure that literal v6 addresses are correclty
    marked in the constructed URL.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c
index a8713eb..1b30c2c 100644
--- a/dirmngr/dns-stuff.c
+++ b/dirmngr/dns-stuff.c
@@ -993,8 +993,10 @@ resolve_dns_addr (const struct sockaddr *addr, int addrlen,
 }
 
 
-/* Check whether NAME is an IP address.  Returns true if it is either
-   an IPv6 or IPv4 numerical address.  */
+/* Check whether NAME is an IP address.  Returns a true if it is
+ * either an IPv6 or a IPv4 numerical address.  The actual return
+ * values can also be used to identify whether it is v4 or v6: The
+ * true value will surprisingly be 4 for IPv4 and 6 for IPv6.  */
 int
 is_ip_address (const char *name)
 {
@@ -1002,7 +1004,7 @@ is_ip_address (const char *name)
   int ndots, dblcol, n;
 
   if (*name == '[')
-    return 1; /* yes: A legal DNS name may not contain this character;
+    return 6; /* yes: A legal DNS name may not contain this character;
                  this mut be bracketed v6 address.  */
   if (*name == '.')
     return 0; /* No.  A leading dot is not a valid IP address.  */
@@ -1035,7 +1037,7 @@ is_ip_address (const char *name)
   if (ndots > 7)
     return 0; /* No: Too many colons.  */
   else if (ndots > 1)
-    return 1; /* Yes: At least 2 colons indicate an v6 address.  */
+    return 6; /* Yes: At least 2 colons indicate an v6 address.  */
 
  legacy:
   /* Check whether it is legacy IP address.  */
@@ -1056,7 +1058,7 @@ is_ip_address (const char *name)
       else if (++n > 3)
         return 0; /* No: More than 3 digits.  */
     }
-  return !!(ndots == 3);
+  return (ndots == 3)? 4 : 0;
 }
 
 
diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
index 5febb13..8c171a5 100644
--- a/dirmngr/ks-engine-hkp.c
+++ b/dirmngr/ks-engine-hkp.c
@@ -384,13 +384,14 @@ add_host (const char *name, int is_pool,
  * NULL is stored.  If we know the port used by the selected host from
  * a service record, a string representation is written to R_PORTSTR,
  * otherwise it is left untouched.  If R_HTTPFLAGS is not NULL it will
- * receive flags which are to be passed to http_open.  If R_POOLNAME
- * is not NULL a malloced name of the pool is stored or NULL if it is
- * not a pool. */
+ * receive flags which are to be passed to http_open.  If R_HTTPHOST
+ * is not NULL a malloced name of the host is stored there; this might
+ * be different from R_HOST in case it has been selected from a
+ * pool.  */
 static gpg_error_t
 map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
           char **r_host, char *r_portstr,
-          unsigned int *r_httpflags, char **r_poolname)
+          unsigned int *r_httpflags, char **r_httphost)
 {
   gpg_error_t err = 0;
   hostinfo_t hi;
@@ -399,8 +400,8 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
   *r_host = NULL;
   if (r_httpflags)
     *r_httpflags = 0;
-  if (r_poolname)
-    *r_poolname = NULL;
+  if (r_httphost)
+    *r_httphost = NULL;
 
   /* No hostname means localhost.  */
   if (!name || !*name)
@@ -535,10 +536,10 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
   if (hi->pool)
     {
       /* Deal with the pool name before selecting a host. */
-      if (r_poolname)
+      if (r_httphost)
         {
-          *r_poolname = xtrystrdup (hi->cname? hi->cname : hi->name);
-          if (!*r_poolname)
+          *r_httphost = xtrystrdup (hi->cname? hi->cname : hi->name);
+          if (!*r_httphost)
             return gpg_error_from_syserror ();
         }
 
@@ -557,10 +558,10 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
           if (hi->poolidx == -1)
             {
               log_error ("no alive host found in pool '%s'\n", name);
-              if (r_poolname)
+              if (r_httphost)
                 {
-                  xfree (*r_poolname);
-                  *r_poolname = NULL;
+                  xfree (*r_httphost);
+                  *r_httphost = NULL;
                 }
               return gpg_error (GPG_ERR_NO_KEYSERVER);
             }
@@ -574,10 +575,10 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
   if (hi->dead)
     {
       log_error ("host '%s' marked as dead\n", hi->name);
-      if (r_poolname)
+      if (r_httphost)
         {
-          xfree (*r_poolname);
-          *r_poolname = NULL;
+          xfree (*r_httphost);
+          *r_httphost = NULL;
         }
       return gpg_error (GPG_ERR_NO_KEYSERVER);
     }
@@ -604,10 +605,10 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
   if (!*r_host)
     {
       err = gpg_error_from_syserror ();
-      if (r_poolname)
+      if (r_httphost)
         {
-          xfree (*r_poolname);
-          *r_poolname = NULL;
+          xfree (*r_httphost);
+          *r_httphost = NULL;
         }
       return err;
     }
@@ -851,13 +852,15 @@ ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri)
 
 /* Build the remote part of the URL from SCHEME, HOST and an optional
  * PORT.  If NO_SRV is set no SRV record lookup will be done.  Returns
- * an allocated string at R_HOSTPORT or NULL on failure If R_POOLNAME
- * is not NULL it receives a malloced string with the poolname.  */
+ * an allocated string at R_HOSTPORT or NULL on failure.  If
+ * R_HTTPHOST is not NULL it receives a malloced string with the
+ * hostname; this may be different from HOST if HOST is selected from
+ * a pool.  */
 static gpg_error_t
 make_host_part (ctrl_t ctrl,
                 const char *scheme, const char *host, unsigned short port,
                 int force_reselect, int no_srv,
-                char **r_hostport, unsigned int *r_httpflags, char **r_poolname)
+                char **r_hostport, unsigned int *r_httpflags, char **r_httphost)
 {
   gpg_error_t err;
   const char *srvtag;
@@ -879,7 +882,7 @@ make_host_part (ctrl_t ctrl,
 
   portstr[0] = 0;
   err = map_host (ctrl, host, srvtag, force_reselect,
-                  &hostname, portstr, r_httpflags, r_poolname);
+                  &hostname, portstr, r_httpflags, r_httphost);
   if (err)
     return err;
 
@@ -896,14 +899,17 @@ make_host_part (ctrl_t ctrl,
   else
     strcpy (portstr, "11371");
 
-  *r_hostport = strconcat (scheme, "://", hostname, ":", portstr, NULL);
+  if (*hostname != '[' && is_ip_address (hostname) == 6)
+    *r_hostport = strconcat (scheme, "://[", hostname, "]:", portstr, NULL);
+  else
+    *r_hostport = strconcat (scheme, "://", hostname, ":", portstr, NULL);
   xfree (hostname);
   if (!*r_hostport)
     {
-      if (r_poolname)
+      if (r_httphost)
         {
-          xfree (*r_poolname);
-          *r_poolname = NULL;
+          xfree (*r_httphost);
+          *r_httphost = NULL;
         }
       return gpg_error_from_syserror ();
     }

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

Summary of changes:
 dirmngr/dns-stuff.c     | 229 ++++++++++++++++++++++++++++++++++++++++--------
 dirmngr/ks-engine-hkp.c |  88 +++++++++++++------
 2 files changed, 254 insertions(+), 63 deletions(-)


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




More information about the Gnupg-commits mailing list