[git] GnuPG - branch, master, updated. gnupg-2.1.21-68-g48aae81

by Justus Winter cvs at cvs.gnupg.org
Tue Jun 20 16:39:54 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  48aae8167dcae80d43b08167a88d9eb170781a04 (commit)
       via  fc4834d213af031b456c49c1ba5b5ef8873d1f18 (commit)
       via  794261c4bdb271060125feda534a26580c6b9f26 (commit)
      from  badc1cdae52bd434e5fac2e4275575afeccc2837 (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 48aae8167dcae80d43b08167a88d9eb170781a04
Author: Justus Winter <justus at g10code.com>
Date:   Tue Jun 20 16:27:59 2017 +0200

    dirmngr: Properly handle SRV records.
    
    * dirmngr/ks-engine-hkp.c (enum ks_protocol): New type.
    (struct hostinfo_s): New flags indicating whether we already did a
    A lookup, or a SRV lookup per protocol.  Turn 'port' into an array.
    (create_new_hostinfo): Initialize new fields.
    (add_host): Update the port for the given protocol.
    (map_host): Simplify hosttable lookup misses.  Check the SRV records
    for both protocols on demand, do the A lookup just once.  Return the
    correct port.
    --
    
    Previously, if a host had both a SRV record for hkp and hkps, the
    wrong port was used for the protocol that was used second, because the
    hostinfo did not store a port per protocol, and the hosttable does not
    discriminate between hosts using the protocol.
    
    Fix this by querying the SRV records on demand, storing a port per
    protocol, and returning the right port.
    
    GnuPG-bug-id: 3033
    Signed-off-by: Justus Winter <justus at g10code.com>

diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
index 9a47ca9..aa98b37 100644
--- a/dirmngr/ks-engine-hkp.c
+++ b/dirmngr/ks-engine-hkp.c
@@ -67,6 +67,8 @@
 /* Number of retries done for a dead host etc.  */
 #define SEND_REQUEST_RETRIES 3
 
+enum ks_protocol { KS_PROTOCOL_HKP, KS_PROTOCOL_HKPS, KS_PROTOCOL_MAX };
+
 /* Objects used to maintain information about hosts.  */
 struct hostinfo_s;
 typedef struct hostinfo_s *hostinfo_t;
@@ -86,12 +88,18 @@ struct hostinfo_s
   unsigned int dead:1; /* Host is currently unresponsive.  */
   unsigned int iporname_valid:1;  /* The field IPORNAME below is valid */
                                   /* (but may be NULL) */
+  unsigned int did_a_lookup:1;    /* Have we done an A lookup yet?  */
+  unsigned int did_srv_lookup:2;  /* One bit per protocol indicating
+                                     whether we already did a SRV
+                                     lookup.  */
   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 or NAME has a numerical IP address.  */
   char *iporname;    /* Numeric IP address or name for printing.  */
-  unsigned short port; /* The port used by the host, 0 if unknown.  */
+  unsigned short port[KS_PROTOCOL_MAX];
+                     /* The port used by the host for all protocols, 0
+                        if unknown.  */
   char name[1];      /* The hostname.  */
 };
 
@@ -129,11 +137,14 @@ create_new_hostinfo (const char *name)
   hi->v6 = 0;
   hi->onion = 0;
   hi->dead = 0;
+  hi->did_a_lookup = 0;
+  hi->did_srv_lookup = 0;
   hi->iporname_valid = 0;
   hi->died_at = 0;
   hi->cname = NULL;
   hi->iporname = NULL;
-  hi->port = 0;
+  hi->port[KS_PROTOCOL_HKP] = 0;
+  hi->port[KS_PROTOCOL_HKPS] = 0;
 
   /* Add it to the hosttable. */
   for (idx=0; idx < hosttable_size; idx++)
@@ -289,12 +300,13 @@ tor_not_running_p (ctrl_t ctrl)
 
 
 /* Add the host AI under the NAME into the HOSTTABLE.  If PORT is not
-   zero, it specifies which port to use to talk to the host.  If NAME
-   specifies a pool (as indicated by IS_POOL), update the given
-   reference table accordingly.  */
+   zero, it specifies which port to use to talk to the host for
+   PROTOCOL.  If NAME specifies a pool (as indicated by IS_POOL),
+   update the given reference table accordingly.  */
 static void
 add_host (const char *name, int is_pool,
-          const dns_addrinfo_t ai, unsigned short port)
+          const dns_addrinfo_t ai,
+          enum ks_protocol protocol, unsigned short port)
 {
   gpg_error_t tmperr;
   char *tmphost;
@@ -361,7 +373,7 @@ add_host (const char *name, int is_pool,
       else  /* Set or update the entry. */
         {
           if (port)
-            hosttable[tmpidx]->port = port;
+            hosttable[tmpidx]->port[protocol] = port;
 
           if (ai->family == AF_INET6)
             {
@@ -439,12 +451,16 @@ hostinfo_sort_pool (hostinfo_t hi)
  * 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,
+          enum ks_protocol protocol, char **r_host, char *r_portstr,
           unsigned int *r_httpflags, char **r_httphost)
 {
   gpg_error_t err = 0;
   hostinfo_t hi;
   int idx;
+  dns_addrinfo_t aibuf, ai;
+  int is_pool;
+  int new_hosts = 0;
+  char *cname;
 
   *r_host = NULL;
   if (r_httpflags)
@@ -461,62 +477,62 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
 
   /* See whether the host is in our table.  */
   idx = find_hostinfo (name);
-  if (idx == -1 && is_onion_address (name))
+  if (idx == -1)
     {
       idx = create_new_hostinfo (name);
       if (idx == -1)
         return gpg_error_from_syserror ();
       hi = hosttable[idx];
-      hi->onion = 1;
+      hi->onion = is_onion_address (name);
     }
-  else if (idx == -1)
+  else
+    hi = hosttable[idx];
+
+  is_pool = hi->pool != NULL;
+
+  if (srvtag && !is_ip_address (name)
+      && ! hi->onion
+      && ! (hi->did_srv_lookup & 1 << protocol))
     {
-      /* We never saw this host.  Allocate a new entry.  */
-      dns_addrinfo_t aibuf, ai;
-      int is_pool = 0;
-      char *cname;
       struct srventry *srvs;
       unsigned int srvscount;
 
-      idx = create_new_hostinfo (name);
-      if (idx == -1)
+      /* Check for SRV records.  */
+      err = get_dns_srv (name, srvtag, NULL, &srvs, &srvscount);
+      if (err)
         {
-          err = gpg_error_from_syserror ();
+          if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
+            tor_not_running_p (ctrl);
           return err;
         }
-      hi = hosttable[idx];
 
-      if (srvtag && !is_ip_address (name))
+      if (srvscount > 0)
         {
-          /* Check for SRV records.  */
-          err = get_dns_srv (name, srvtag, NULL, &srvs, &srvscount);
-          if (err)
-            {
-              if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
-                tor_not_running_p (ctrl);
-              return err;
-            }
+          int i;
+          if (! is_pool)
+            is_pool = srvscount > 1;
 
-          if (srvscount > 0)
+          for (i = 0; i < srvscount; i++)
             {
-              int i;
-              is_pool = srvscount > 1;
-
-              for (i = 0; i < srvscount; i++)
-                {
-                  err = resolve_dns_name (srvs[i].target, 0,
-                                          AF_UNSPEC, SOCK_STREAM,
-                                          &ai, &cname);
-                  if (err)
-                    continue;
-                  dirmngr_tick (ctrl);
-                  add_host (name, is_pool, ai, srvs[i].port);
-                }
-
-              xfree (srvs);
+              err = resolve_dns_name (srvs[i].target, 0,
+                                      AF_UNSPEC, SOCK_STREAM,
+                                      &ai, &cname);
+              if (err)
+                continue;
+              dirmngr_tick (ctrl);
+              add_host (name, is_pool, ai, protocol, srvs[i].port);
+              new_hosts = 1;
             }
+
+          xfree (srvs);
         }
 
+      hi->did_srv_lookup |= 1 << protocol;
+    }
+
+  if (! hi->did_a_lookup
+      && ! hi->onion)
+    {
       /* Find all A records for this entry and put them into the pool
          list - if any.  */
       err = resolve_dns_name (name, 0, 0, SOCK_STREAM, &aibuf, &cname);
@@ -550,15 +566,18 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
                 continue;
               dirmngr_tick (ctrl);
 
-              add_host (name, is_pool, ai, 0);
+              add_host (name, is_pool, ai, 0, 0);
+              new_hosts = 1;
             }
+
+          hi->did_a_lookup = 1;
         }
       xfree (cname);
       free_dns_addrinfo (aibuf);
-      hostinfo_sort_pool (hi);
     }
+  if (new_hosts)
+    hostinfo_sort_pool (hi);
 
-  hi = hosttable[idx];
   if (hi->pool)
     {
       /* Deal with the pool name before selecting a host. */
@@ -603,7 +622,6 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
        * 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);
@@ -667,9 +685,9 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
         }
       return err;
     }
-  if (hi->port)
+  if (hi->port[protocol])
     snprintf (r_portstr, 6 /* five digits and the sentinel */,
-              "%hu", hi->port);
+              "%hu", hi->port[protocol]);
   return 0;
 }
 
@@ -990,6 +1008,7 @@ make_host_part (ctrl_t ctrl,
   const char *srvtag;
   char portstr[10];
   char *hostname;
+  enum ks_protocol protocol;
 
   *r_hostport = NULL;
 
@@ -997,15 +1016,17 @@ make_host_part (ctrl_t ctrl,
     {
       scheme = "https";
       srvtag = no_srv? NULL : "pgpkey-https";
+      protocol = KS_PROTOCOL_HKPS;
     }
   else /* HKP or HTTP.  */
     {
       scheme = "http";
       srvtag = no_srv? NULL : "pgpkey-http";
+      protocol = KS_PROTOCOL_HKP;
     }
 
   portstr[0] = 0;
-  err = map_host (ctrl, host, srvtag, force_reselect,
+  err = map_host (ctrl, host, srvtag, force_reselect, protocol,
                   &hostname, portstr, r_httpflags, r_httphost);
   if (err)
     return err;

commit fc4834d213af031b456c49c1ba5b5ef8873d1f18
Author: Justus Winter <justus at g10code.com>
Date:   Tue Jun 20 14:54:17 2017 +0200

    dirmngr: Refactor variable-sized array code.
    
    * dirmngr/ks-engine-hkp.c (struct hostinfo_s): Add explicit length and
    size fields.
    (MAX_POOL_SIZE): New macro.
    (create_new_hostinfo): Initialize new fields.
    (host_in_pool_p): Adapt.
    (select_random_host): Likewise.
    (add_host): Likewise.  Move the resizing logic here.
    (hostinfo_sort_pool): New function.
    (map_host): Simplify.  Move the resizing logic away from here.
    (ks_hkp_mark_host): Adapt.
    (ks_hkp_print_hosttable): Likewise.
    --
    
    The current code assumes that the pool array is only filled when the
    hostinfo object is created.  This patch removes that limitation.
    
    GnuPG-bug-id: 3033
    Signed-off-by: Justus Winter <justus at g10code.com>

diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
index 25ec9cb..9a47ca9 100644
--- a/dirmngr/ks-engine-hkp.c
+++ b/dirmngr/ks-engine-hkp.c
@@ -74,9 +74,11 @@ struct hostinfo_s
 {
   time_t lastfail;   /* Time we tried to connect and failed.  */
   time_t lastused;   /* Time of last use.  */
-  int *pool;         /* A -1 terminated array with indices into
-                        HOSTTABLE or NULL if NAME is not a pool
-                        name.  */
+  int *pool;         /* An array with indices into HOSTTABLE or NULL
+                        if NAME is not a pool name.  */
+  size_t pool_len;   /* Length of POOL.  */
+  size_t pool_size;  /* Allocated size of POOL.  */
+#define MAX_POOL_SIZE	128
   int poolidx;       /* Index into POOL with the used host.  -1 if not set.  */
   unsigned int v4:1; /* Host supports AF_INET.  */
   unsigned int v6:1; /* Host supports AF_INET6.  */
@@ -118,6 +120,8 @@ create_new_hostinfo (const char *name)
     return -1;
   strcpy (hi->name, name);
   hi->pool = NULL;
+  hi->pool_len = 0;
+  hi->pool_size = 0;
   hi->poolidx = -1;
   hi->lastused = (time_t)(-1);
   hi->lastfail = (time_t)(-1);
@@ -187,24 +191,24 @@ sort_hostpool (const void *xa, const void *xb)
 }
 
 
-/* Return true if the host with the hosttable index TBLIDX is in POOL.  */
+/* Return true if the host with the hosttable index TBLIDX is in HI->pool.  */
 static int
-host_in_pool_p (int *pool, int tblidx)
+host_in_pool_p (hostinfo_t hi, int tblidx)
 {
   int i, pidx;
 
-  for (i=0; (pidx = pool[i]) != -1; i++)
+  for (i = 0; i < hi->pool_len && (pidx = hi->pool[i]) != -1; i++)
     if (pidx == tblidx && hosttable[pidx])
       return 1;
   return 0;
 }
 
 
-/* Select a random host.  Consult TABLE which indices into the global
-   hosttable.  Returns index into TABLE or -1 if no host could be
+/* Select a random host.  Consult HI->pool which indices into the global
+   hosttable.  Returns index into HI->pool or -1 if no host could be
    selected.  */
 static int
-select_random_host (int *table)
+select_random_host (hostinfo_t hi)
 {
   int *tbl;
   size_t tblsize;
@@ -212,7 +216,9 @@ select_random_host (int *table)
 
   /* We create a new table so that we randomly select only from
      currently alive hosts.  */
-  for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
+  for (idx = 0, tblsize = 0;
+       idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
+       idx++)
     if (hosttable[pidx] && !hosttable[pidx]->dead)
       tblsize++;
   if (!tblsize)
@@ -221,7 +227,9 @@ select_random_host (int *table)
   tbl = xtrymalloc (tblsize * sizeof *tbl);
   if (!tbl)
     return -1;
-  for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
+  for (idx = 0, tblsize = 0;
+       idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
+       idx++)
     if (hosttable[pidx] && !hosttable[pidx]->dead)
       tbl[tblsize++] = pidx;
 
@@ -286,15 +294,16 @@ tor_not_running_p (ctrl_t ctrl)
    reference table accordingly.  */
 static void
 add_host (const char *name, int is_pool,
-          const dns_addrinfo_t ai, unsigned short port,
-          int *reftbl, size_t reftblsize, int *refidx)
+          const dns_addrinfo_t ai, unsigned short port)
 {
   gpg_error_t tmperr;
   char *tmphost;
   int idx, tmpidx;
+  hostinfo_t host;
   int i;
 
   idx = find_hostinfo (name);
+  host = hosttable[idx];
 
   if (is_pool)
     {
@@ -325,7 +334,7 @@ add_host (const char *name, int is_pool,
       log_info ("resolve_dns_addr failed while checking '%s': %s\n",
                 name, gpg_strerror (tmperr));
     }
-  else if ((*refidx) + 1 >= reftblsize)
+  else if (host->pool_len + 1 >= MAX_POOL_SIZE)
     {
       log_error ("resolve_dns_addr for '%s': '%s'"
                  " [index table full - ignored]\n", name, tmphost);
@@ -365,17 +374,54 @@ add_host (const char *name, int is_pool,
           else
             BUG ();
 
-          for (i=0; i < *refidx; i++)
-            if (reftbl[i] == tmpidx)
-              break;
-          if (!(i < *refidx) && tmpidx != idx)
-            reftbl[(*refidx)++] = tmpidx;
+          /* If we updated the main entry, we're done.  */
+          if (idx == tmpidx)
+            goto leave;
+
+          /* If we updated an existing entry, we're done.  */
+          for (i = 0; i < host->pool_len; i++)
+            if (host->pool[i] == tmpidx)
+              goto leave;
+
+          /* Otherwise, we need to add it to the pool.  Check if there
+             is space.  */
+          if (host->pool_len + 1 > host->pool_size)
+            {
+              int *new_pool;
+              size_t new_size;
+
+              if (host->pool_size == 0)
+                new_size = 4;
+              else
+                new_size = host->pool_size * 2;
+
+              new_pool = xtryrealloc (host->pool,
+                                      new_size * sizeof *new_pool);
+
+              if (new_pool == NULL)
+                goto leave;
+
+              host->pool = new_pool;
+              host->pool_size = new_size;
+            }
+
+          /* Finally, add it.  */
+          log_assert (host->pool_len < host->pool_size);
+          host->pool[host->pool_len++] = tmpidx;
         }
     }
+ leave:
   xfree (tmphost);
 }
 
 
+/* Sort the pool of the given hostinfo HI.  */
+static void
+hostinfo_sort_pool (hostinfo_t hi)
+{
+  qsort (hi->pool, hi->pool_len, sizeof *hi->pool, sort_hostpool);
+}
+
 /* Map the host name NAME to the actual to be used host name.  This
  * allows us to manage round robin DNS names.  We use our own strategy
  * to choose one of the hosts.  For example we skip those hosts which
@@ -427,25 +473,15 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
     {
       /* We never saw this host.  Allocate a new entry.  */
       dns_addrinfo_t aibuf, ai;
-      int *reftbl;
-      size_t reftblsize;
-      int refidx;
       int is_pool = 0;
       char *cname;
       struct srventry *srvs;
       unsigned int srvscount;
 
-      reftblsize = 100;
-      reftbl = xtrymalloc (reftblsize * sizeof *reftbl);
-      if (!reftbl)
-        return gpg_error_from_syserror ();
-      refidx = 0;
-
       idx = create_new_hostinfo (name);
       if (idx == -1)
         {
           err = gpg_error_from_syserror ();
-          xfree (reftbl);
           return err;
         }
       hi = hosttable[idx];
@@ -456,7 +492,6 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
           err = get_dns_srv (name, srvtag, NULL, &srvs, &srvscount);
           if (err)
             {
-              xfree (reftbl);
               if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
                 tor_not_running_p (ctrl);
               return err;
@@ -475,8 +510,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
                   if (err)
                     continue;
                   dirmngr_tick (ctrl);
-                  add_host (name, is_pool, ai, srvs[i].port,
-                            reftbl, reftblsize, &refidx);
+                  add_host (name, is_pool, ai, srvs[i].port);
                 }
 
               xfree (srvs);
@@ -516,29 +550,12 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
                 continue;
               dirmngr_tick (ctrl);
 
-              add_host (name, is_pool, ai, 0, reftbl, reftblsize, &refidx);
+              add_host (name, is_pool, ai, 0);
             }
         }
-      reftbl[refidx] = -1;
       xfree (cname);
       free_dns_addrinfo (aibuf);
-
-      if (refidx && is_pool)
-        {
-          assert (!hi->pool);
-          hi->pool = xtryrealloc (reftbl, (refidx+1) * sizeof *reftbl);
-          if (!hi->pool)
-            {
-              err = gpg_error_from_syserror ();
-              log_error ("shrinking index table in map_host failed: %s\n",
-                         gpg_strerror (err));
-              xfree (reftbl);
-              return err;
-            }
-          qsort (hi->pool, refidx, sizeof *reftbl, sort_hostpool);
-        }
-      else
-        xfree (reftbl);
+      hostinfo_sort_pool (hi);
     }
 
   hi = hosttable[idx];
@@ -563,7 +580,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
       /* Select a host if needed.  */
       if (hi->poolidx == -1)
         {
-          hi->poolidx = select_random_host (hi->pool);
+          hi->poolidx = select_random_host (hi);
           if (hi->poolidx == -1)
             {
               log_error ("no alive host found in pool '%s'\n", name);
@@ -740,7 +757,9 @@ ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
   /* If the host is a pool mark all member hosts. */
   if (!err && hi->pool)
     {
-      for (idx2=0; !err && (n=hi->pool[idx2]) != -1; idx2++)
+      for (idx2 = 0;
+           !err && idx2 < hi->pool_len && (n = hi->pool[idx2]) != -1;
+           idx2++)
         {
           assert (n >= 0 && n < hosttable_size);
 
@@ -753,7 +772,7 @@ ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
                   if (hosttable[idx3]
                       && hosttable[idx3]->pool
                       && idx3 != idx
-                      && host_in_pool_p (hosttable[idx3]->pool, n))
+                      && host_in_pool_p (hosttable[idx3], n))
                     break;
                 }
               if (idx3 < hosttable_size)
@@ -903,7 +922,7 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
           {
             init_membuf (&mb, 256);
             put_membuf_printf (&mb, "  .   -->");
-            for (idx2=0; hi->pool[idx2] != -1; idx2++)
+            for (idx2 = 0; idx2 < hi->pool_len && hi->pool[idx2] != -1; idx2++)
               {
                 put_membuf_printf (&mb, " %d", hi->pool[idx2]);
                 if (hi->poolidx == hi->pool[idx2])

commit 794261c4bdb271060125feda534a26580c6b9f26
Author: Justus Winter <justus at g10code.com>
Date:   Tue Jun 20 13:34:12 2017 +0200

    dirmngr: Fix typo.
    
    --
    Signed-off-by: Justus Winter <justus at g10code.com>

diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
index bcdcffa..25ec9cb 100644
--- a/dirmngr/ks-engine-hkp.c
+++ b/dirmngr/ks-engine-hkp.c
@@ -255,7 +255,7 @@ arecords_is_pool (dns_addrinfo_t aibuf)
 }
 
 
-/* Print a warninng iff Tor is not running but Tor has been requested.
+/* Print a warning iff Tor is not running but Tor has been requested.
  * Also return true if it is not running.  */
 static int
 tor_not_running_p (ctrl_t ctrl)

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

Summary of changes:
 dirmngr/ks-engine-hkp.c | 246 ++++++++++++++++++++++++++++--------------------
 1 file changed, 143 insertions(+), 103 deletions(-)


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




More information about the Gnupg-commits mailing list