[git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-423-gd2d9d4f

by Werner Koch cvs at cvs.gnupg.org
Fri May 16 21:14:54 CEST 2014


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  d2d9d4fb60e3f2160af6252335364d3aac4b7d17 (commit)
       via  8b90d79818355b81ce223e1cb96cd0c939096fe2 (commit)
      from  25036ec6abbc0c9d0003dcfe227724038c35a304 (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 d2d9d4fb60e3f2160af6252335364d3aac4b7d17
Author: Werner Koch <wk at gnupg.org>
Date:   Fri May 16 21:14:03 2014 +0200

    keyserver: Improve support for hkps pools.
    
    * dirmngr/ks-engine-hkp.c (hostinfo_s): Add fields cname, v4addr, and
    v6addr.
    (create_new_hostinfo): Clear them.
    (my_getnameinfo): Add args numeric and r_isnumeric.
    (is_ip_address): New.
    (map_host): Add arg r_host.  Rewrite the code to handle pools in a
    special way.
    (ks_hkp_print_hosttable): Change format of help info output.
    (make_host_part): Add arg optional r_httphost.
    (send_request): Add arg httphost.
    (ks_hkp_search, ks_hkp_get, ks_hkp_put): Get httphost and pass it to
    send_request.
    --
    
    This changes quite some things on how the hostinfo is maintained.
    However, it might be better to rework the data structures and have one
    entry per IP address instead of this clumsy patch.

diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
index 541c46f..3c25953 100644
--- a/dirmngr/ks-engine-hkp.c
+++ b/dirmngr/ks-engine-hkp.c
@@ -69,12 +69,20 @@ struct hostinfo_s
   int *pool;         /* A -1 terminated array with indices into
                         HOSTTABLE or NULL if NAME is not a pool
                         name.  */
-  int poolidx;       /* Index into POOL with the used host.  */
+  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.  */
   unsigned int dead:1; /* Host is currently unresponsive.  */
-  time_t died_at;    /* The time the host was marked dead.  IF this is
+  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.  */
+  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.  */
+  char *v6addr;      /* A string with the v6 IP address of the host.
+                        NULL if NAME has a numeric IP address or no v4
+                        address is available.  */
   char name[1];      /* The hostname.  */
 };
 
@@ -110,6 +118,9 @@ create_new_hostinfo (const char *name)
   hi->v6 = 0;
   hi->dead = 0;
   hi->died_at = 0;
+  hi->cname = NULL;
+  hi->v4addr = NULL;
+  hi->v6addr = NULL;
 
   /* Add it to the hosttable. */
   for (idx=0; idx < hosttable_size; idx++)
@@ -217,19 +228,28 @@ select_random_host (int *table)
 
 /* Simplified version of getnameinfo which also returns a numeric
    hostname inside of brackets.  The caller should provide a buffer
-   for TMPHOST which is 2 bytes larger than the the largest hostname.
-   returns 0 on success or an EAI error code.  */
+   for HOST which is 2 bytes larger than the largest hostname.  If
+   NUMERIC is true the returned value is numeric IP address.  Returns
+   0 on success or an EAI error code.  True is stored at R_ISNUMERIC
+   if HOST has a numeric IP address. */
 static int
-my_getnameinfo (struct addrinfo *ai, char *host, size_t hostlen)
+my_getnameinfo (struct addrinfo *ai, char *host, size_t hostlen,
+                int numeric, int *r_isnumeric)
 {
   int ec;
   char *p;
 
+  *r_isnumeric = 0;
+
   if (hostlen < 5)
     return EAI_OVERFLOW;
 
-  ec = getnameinfo (ai->ai_addr, ai->ai_addrlen,
-                    host, hostlen, NULL, 0, NI_NAMEREQD);
+  if (numeric)
+    ec = EAI_NONAME;
+  else
+    ec = getnameinfo (ai->ai_addr, ai->ai_addrlen,
+                      host, hostlen, NULL, 0, NI_NAMEREQD);
+
   if (!ec && *host == '[')
     ec = EAI_FAIL;  /* A name may never start with a bracket.  */
   else if (ec == EAI_NONAME)
@@ -244,28 +264,66 @@ my_getnameinfo (struct addrinfo *ai, char *host, size_t hostlen)
                         p, hostlen, NULL, 0, NI_NUMERICHOST);
       if (!ec && ai->ai_family == AF_INET6)
         strcat (host, "]");
+
+      *r_isnumeric = 1;
     }
 
   return ec;
 }
 
 
+/* Check whether NAME is an IP address.  */
+static int
+is_ip_address (const char *name)
+{
+  int ndots, n;
+
+  if (*name == '[')
+    return 1;
+  /* Check whether it is legacy IP address.  */
+  if (*name == '.')
+    return 0; /* No.  */
+  ndots = n = 0;
+  for (; *name; name++)
+    {
+      if (*name == '.')
+        {
+          if (name[1] == '.')
+            return 0; /* No. */
+          if (atoi (name+1) > 255)
+            return 0; /* Value too large.  */
+          ndots++;
+          n = 0;
+        }
+      else if (!strchr ("012345678", *name))
+        return 0; /* Not a digit.  */
+      else if (++n > 3)
+        return 0; /* More than 3 digits.  */
+    }
+  return !!(ndots == 3);
+}
+
+
 /* 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
    failed for some time and we stick to one host for a time
    independent of DNS retry times.  If FORCE_RESELECT is true a new
    host is always selected.  If R_HTTPFLAGS is not NULL if will
-   received flags which are to be passed to http_open. */
+   receive flags which are to be passed to http_open.  If R_HOST is
+   not NULL a malloced name of the pool is stored or NULL if it is not
+   a pool. */
 static char *
 map_host (ctrl_t ctrl, const char *name, int force_reselect,
-          unsigned int *r_httpflags)
+          unsigned int *r_httpflags, char **r_host)
 {
   hostinfo_t hi;
   int idx;
 
   if (r_httpflags)
     *r_httpflags = 0;
+  if (r_host)
+    *r_host = NULL;
 
   /* No hostname means localhost.  */
   if (!name || !*name)
@@ -280,6 +338,7 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
       int *reftbl;
       size_t reftblsize;
       int refidx;
+      int is_pool = 0;
 
       reftblsize = 100;
       reftbl = xtrymalloc (reftblsize * sizeof *reftbl);
@@ -298,13 +357,40 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
       /* Find all A records for this entry and put them into the pool
          list - if any.  */
       memset (&hints, 0, sizeof (hints));
+      hints.ai_family = AF_UNSPEC;
       hints.ai_socktype = SOCK_STREAM;
+      hints.ai_flags = AI_CANONNAME;
+      /* We can't use the the AI_IDN flag because that does the
+         conversion using the current locale.  However, GnuPG always
+         used UTF-8.  To support IDN we would need to make use of the
+         libidn API.  */
       if (!getaddrinfo (name, NULL, &hints, &aibuf))
         {
+          int n_v6, n_v4;
+
+          /* First figure out whether this is a pool.  For a pool we
+             use a different strategy than for a plains erver: We use
+             the canonical name of the pool as the virtual host along
+             with the IP addresses.  If it is not a pool, we use the
+             specified name. */
+          n_v6 = n_v4 = 0;
           for (ai = aibuf; ai; ai = ai->ai_next)
             {
-              char tmphost[NI_MAXHOST];
+              if (ai->ai_family != AF_INET6)
+                n_v6++;
+              else if (ai->ai_family != AF_INET)
+                n_v4++;
+            }
+          if (n_v6 > 1 || n_v4 > 1)
+            is_pool = 1;
+          if (is_pool && aibuf->ai_canonname)
+            hi->cname = xtrystrdup (aibuf->ai_canonname);
+
+          for (ai = aibuf; ai; ai = ai->ai_next)
+            {
+              char tmphost[NI_MAXHOST + 2];
               int tmpidx;
+              int is_numeric;
               int ec;
               int i;
 
@@ -312,7 +398,28 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
                 continue;
 
               dirmngr_tick (ctrl);
-              if ((ec = my_getnameinfo (ai, tmphost, sizeof tmphost)))
+
+              if (!is_pool && !is_ip_address (name))
+                {
+                  /* This is a hostname but not a pool.  Use the name
+                     as given without going through getnameinfo.  */
+                  if (strlen (name)+1 > sizeof tmphost)
+                    {
+                      ec = EAI_SYSTEM;
+                      gpg_err_set_errno (EINVAL);
+                    }
+                  else
+                    {
+                      ec = 0;
+                      strcpy (tmphost, name);
+                    }
+                  is_numeric = 0;
+                }
+              else
+                ec = my_getnameinfo (ai, tmphost, sizeof tmphost,
+                                     0, &is_numeric);
+
+              if (ec)
                 {
                   log_info ("getnameinfo failed while checking '%s': %s\n",
                             name, gai_strerror (ec));
@@ -324,15 +431,49 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
                 }
               else
                 {
+                  tmpidx = find_hostinfo (tmphost);
+                  log_info ("getnameinfo returned for '%s': '%s'%s\n",
+                            name, tmphost,
+                            tmpidx == -1? "" : " [already known]");
+
+                  if (tmpidx == -1) /* Create a new entry.  */
+                    tmpidx = create_new_hostinfo (tmphost);
 
-                  if ((tmpidx = find_hostinfo (tmphost)) != -1)
+                  if (tmpidx == -1)
+                    {
+                      log_error ("map_host for '%s' problem: %s - '%s'"
+                                 " [ignored]\n",
+                                 name, strerror (errno), tmphost);
+                    }
+                  else  /* Set or update the entry. */
                     {
-                      log_info ("getnameinfo returned for '%s': '%s'"
-                                " [already known]\n", name, tmphost);
-                      if (ai->ai_family == AF_INET)
-                        hosttable[tmpidx]->v4 = 1;
+                      char *ipaddr = NULL;
+
+                      if (!is_numeric)
+                        {
+                          ec = my_getnameinfo (ai, tmphost, sizeof tmphost,
+                                               1, &is_numeric);
+                          if (!ec && !(ipaddr = xtrystrdup (tmphost)))
+                            ec = EAI_SYSTEM;
+                          if (ec)
+                            log_info ("getnameinfo failed: %s\n",
+                                      gai_strerror (ec));
+                        }
+
                       if (ai->ai_family == AF_INET6)
-                        hosttable[tmpidx]->v6 = 1;
+                        {
+                          hosttable[tmpidx]->v6 = 1;
+                          xfree (hosttable[tmpidx]->v6addr);
+                          hosttable[tmpidx]->v6addr = ipaddr;
+                        }
+                      else if (ai->ai_family == AF_INET)
+                        {
+                          hosttable[tmpidx]->v4 = 1;
+                          xfree (hosttable[tmpidx]->v4addr);
+                          hosttable[tmpidx]->v4addr = ipaddr;
+                        }
+                      else
+                        BUG ();
 
                       for (i=0; i < refidx; i++)
                         if (reftbl[i] == tmpidx)
@@ -340,35 +481,12 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
                       if (!(i < refidx) && tmpidx != idx)
                         reftbl[refidx++] = tmpidx;
                     }
-                  else
-                    {
-                      log_info ("getnameinfo returned for '%s': '%s'\n",
-                                name, tmphost);
-                      /* Create a new entry.  */
-                      tmpidx = create_new_hostinfo (tmphost);
-                      if (tmpidx == -1)
-                        log_error ("map_host for '%s' problem: %s - '%s'"
-                                   " [ignored]\n",
-                                   name, strerror (errno), tmphost);
-                      else
-                        {
-                          if (ai->ai_family == AF_INET)
-                            hosttable[tmpidx]->v4 = 1;
-                          if (ai->ai_family == AF_INET6)
-                            hosttable[tmpidx]->v6 = 1;
-
-                          for (i=0; i < refidx; i++)
-                            if (reftbl[i] == tmpidx)
-                              break;
-                          if (!(i < refidx) && tmpidx != idx)
-                            reftbl[refidx++] = tmpidx;
-                        }
-                    }
                 }
             }
+          freeaddrinfo (aibuf);
         }
       reftbl[refidx] = -1;
-      if (refidx)
+      if (refidx && is_pool)
         {
           assert (!hi->pool);
           hi->pool = xtryrealloc (reftbl, (refidx+1) * sizeof *reftbl);
@@ -423,12 +541,16 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
          supports IPv<N>, we explicit set the corresponding http
          flags.  The reason for this is that a host might be listed in
          a pool as not v6 only but actually support v6 when later
-         resolved the name is resolved by our http layer.  */
+         the name is resolved by our http layer.  */
       if (!hi->v4)
         *r_httpflags |= HTTP_FLAG_IGNORE_IPv4;
       if (!hi->v6)
         *r_httpflags |= HTTP_FLAG_IGNORE_IPv6;
     }
+
+  if (r_host && hi->pool && hi->cname)
+    *r_host = xtrystrdup (hi->cname);
+
   return xtrystrdup (hi->name);
 }
 
@@ -571,7 +693,7 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
   char *p, *died;
   const char *diedstr;
 
-  err = ks_print_help (ctrl, "hosttable (idx, ipv4, ipv6, dead, name, time):");
+  err = ks_print_help (ctrl, "hosttable (idx, ipv6, ipv4, dead, name, time):");
   if (err)
     return err;
 
@@ -586,16 +708,26 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
           }
         else
           diedstr = died = NULL;
-        err = ks_printf_help (ctrl, "%3d %s %s %s %s%s%s%s\n",
-                              idx, hi->v4? "4":" ", hi->v6? "6":" ",
-                              hi->dead? "d":" ", hi->name,
+        err = ks_printf_help (ctrl, "%3d %s %s %s %s%s%s%s%s%s%s%s\n",
+                              idx, hi->v6? "6":" ", hi->v4? "4":" ",
+                              hi->dead? "d":" ",
+                              hi->name,
+                              hi->v6addr? " v6=":"",
+                              hi->v6addr? hi->v6addr:"",
+                              hi->v4addr? " v4=":"",
+                              hi->v4addr? hi->v4addr:"",
                               diedstr? "  (":"",
                               diedstr? diedstr:"",
                               diedstr? ")":""   );
         xfree (died);
+        if (err)
+          return err;
 
+        if (hi->cname)
+          err = ks_printf_help (ctrl, "  .       %s", hi->cname);
         if (err)
           return err;
+
         if (hi->pool)
           {
             init_membuf (&mb, 256);
@@ -644,13 +776,15 @@ ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri)
 }
 
 
-/* Build the remote part or the URL from SCHEME, HOST and an optional
+/* Build the remote part of the URL from SCHEME, HOST and an optional
    PORT.  Returns an allocated string or NULL on failure and sets
-   ERRNO.  */
+   ERRNO.  If R_HTTPHOST is not NULL it receive a mallcoed string with
+   the poolname.  */
 static char *
 make_host_part (ctrl_t ctrl,
                 const char *scheme, const char *host, unsigned short port,
-                int force_reselect, unsigned int *r_httpflags)
+                int force_reselect,
+                unsigned int *r_httpflags, char **r_httphost)
 {
   char portstr[10];
   char *hostname;
@@ -674,7 +808,7 @@ make_host_part (ctrl_t ctrl,
       /*fixme_do_srv_lookup ()*/
     }
 
-  hostname = map_host (ctrl, host, force_reselect, r_httpflags);
+  hostname = map_host (ctrl, host, force_reselect, r_httpflags, r_httphost);
   if (!hostname)
     return NULL;
 
@@ -693,7 +827,8 @@ ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri)
   gpg_error_t err;
   char *hostport = NULL;
 
-  hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port, 1, NULL);
+  hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port, 1,
+                             NULL, NULL);
   if (!hostport)
     {
       err = gpg_error_from_syserror ();
@@ -739,12 +874,13 @@ ks_hkp_housekeeping (time_t curtime)
 
 
 /* Send an HTTP request.  On success returns an estream object at
-   R_FP.  HOSTPORTSTR is only used for diagnostics.  If POST_CB is not
+   R_FP.  HOSTPORTSTR is only used for diagnostics.  If HTTPHOST is
+   not NULL it will be used as HTTP "Host" header.  If POST_CB is not
    NULL a post request is used and that callback is called to allow
    writing the post data.  */
 static gpg_error_t
 send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
-              unsigned int httpflags,
+              const char *httphost, unsigned int httpflags,
               gpg_error_t (*post_cb)(void *, http_t), void *post_cb_value,
               estream_t *r_fp)
 {
@@ -765,7 +901,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
   err = http_open (&http,
                    post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
                    request,
-                   NULL,
+                   httphost,
                    /* fixme: AUTH */ NULL,
                    httpflags,
                    /* fixme: proxy*/ NULL,
@@ -987,6 +1123,7 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
   estream_t fp = NULL;
   int reselect;
   unsigned int httpflags;
+  char *httphost = NULL;
   unsigned int tries = SEND_REQUEST_RETRIES;
 
   *r_fp = NULL;
@@ -1035,8 +1172,9 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
     char *searchkey;
 
     xfree (hostport);
+    xfree (httphost); httphost = NULL;
     hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
-                               reselect, &httpflags);
+                               reselect, &httpflags, &httphost);
     if (!hostport)
       {
         err = gpg_error_from_syserror ();
@@ -1064,7 +1202,8 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
   }
 
   /* Send the request.  */
-  err = send_request (ctrl, request, hostport, httpflags, NULL, NULL, &fp);
+  err = send_request (ctrl, request, hostport, httphost, httpflags,
+                      NULL, NULL, &fp);
   if (handle_send_request_error (err, request, &tries))
     {
       reselect = 1;
@@ -1104,6 +1243,7 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
   es_fclose (fp);
   xfree (request);
   xfree (hostport);
+  xfree (httphost);
   return err;
 }
 
@@ -1123,6 +1263,7 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
   char *request = NULL;
   estream_t fp = NULL;
   int reselect;
+  char *httphost = NULL;
   unsigned int httpflags;
   unsigned int tries = SEND_REQUEST_RETRIES;
 
@@ -1174,8 +1315,9 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
  again:
   /* Build the request string.  */
   xfree (hostport);
+  xfree (httphost); httphost = NULL;
   hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
-                             reselect, &httpflags);
+                             reselect, &httpflags, &httphost);
   if (!hostport)
     {
       err = gpg_error_from_syserror ();
@@ -1195,7 +1337,8 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
     }
 
   /* Send the request.  */
-  err = send_request (ctrl, request, hostport, httpflags, NULL, NULL, &fp);
+  err = send_request (ctrl, request, hostport, httphost, httpflags,
+                      NULL, NULL, &fp);
   if (handle_send_request_error (err, request, &tries))
     {
       reselect = 1;
@@ -1216,6 +1359,7 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
   es_fclose (fp);
   xfree (request);
   xfree (hostport);
+  xfree (httphost);
   xfree (searchkey);
   return err;
 }
@@ -1263,6 +1407,7 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
   struct put_post_parm_s parm;
   char *armored = NULL;
   int reselect;
+  char *httphost = NULL;
   unsigned int httpflags;
   unsigned int tries = SEND_REQUEST_RETRIES;
 
@@ -1285,8 +1430,9 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
   reselect = 0;
  again:
   xfree (hostport);
+  xfree (httphost); httphost = NULL;
   hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
-                             reselect, &httpflags);
+                             reselect, &httpflags, &httphost);
   if (!hostport)
     {
       err = gpg_error_from_syserror ();
@@ -1302,7 +1448,8 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
     }
 
   /* Send the request.  */
-  err = send_request (ctrl, request, hostport, 0, put_post_cb, &parm, &fp);
+  err = send_request (ctrl, request, hostport, httphost, 0,
+                      put_post_cb, &parm, &fp);
   if (handle_send_request_error (err, request, &tries))
     {
       reselect = 1;
@@ -1317,5 +1464,6 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
   xfree (armored);
   xfree (request);
   xfree (hostport);
+  xfree (httphost);
   return err;
 }

commit 8b90d79818355b81ce223e1cb96cd0c939096fe2
Author: Werner Koch <wk at gnupg.org>
Date:   Fri May 16 20:58:58 2014 +0200

    http: Allow overriding of the Host header.
    
    * common/http.c (http_open): Add arg httphost.
    (http_open_document): Pass NULL for httphost.
    (send_request): Add arg httphost.  If given, use HTTPHOST instead of
    SERVER.  Use https with a proxy if requested.
    (http_verify_server_credentials): Do not stop at the first error
    message.
    * dirmngr/ocsp.c (do_ocsp_request): Adjust call to http_open.
    * keyserver/curl-shim.c (curl_easy_perform): Ditto.
    * dirmngr/ks-engine-http.c (ks_http_fetch): Ditto.
    * dirmngr/ks-engine-hkp.c (ks_hkp_help): Ditto.

diff --git a/common/http.c b/common/http.c
index eb95dcb..8a1ad67 100644
--- a/common/http.c
+++ b/common/http.c
@@ -168,7 +168,8 @@ static int remove_escapes (char *string);
 static int insert_escapes (char *buffer, const char *string,
                            const char *special);
 static uri_tuple_t parse_tuple (char *string);
-static gpg_error_t send_request (http_t hd, const char *auth,const char *proxy,
+static gpg_error_t send_request (http_t hd, const char *httphost,
+                                 const char *auth,const char *proxy,
 				 const char *srvtag,strlist_t headers);
 static char *build_rel_path (parsed_uri_t uri);
 static gpg_error_t parse_response (http_t hd);
@@ -643,11 +644,13 @@ http_session_ref (http_session_t sess)
 }
 
 
-/* Start a HTTP retrieval and return on success in R_HD a context
-   pointer for completing the the request and to wait for the
-   response.  */
+/* Start a HTTP retrieval and on success store at R_HD a context
+   pointer for completing the request and to wait for the response.
+   If HTTPHOST is not NULL it is used hor the Host header instead of a
+   Host header derived from the URL. */
 gpg_error_t
 http_open (http_t *r_hd, http_req_t reqtype, const char *url,
+           const char *httphost,
            const char *auth, unsigned int flags, const char *proxy,
            http_session_t session, const char *srvtag, strlist_t headers)
 {
@@ -669,7 +672,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
 
   err = parse_uri (&hd->uri, url, 0, !!(flags & HTTP_FLAG_FORCE_TLS));
   if (!err)
-    err = send_request (hd, auth, proxy, srvtag, headers);
+    err = send_request (hd, httphost, auth, proxy, srvtag, headers);
 
   if (err)
     {
@@ -868,7 +871,7 @@ http_open_document (http_t *r_hd, const char *document,
 {
   gpg_error_t err;
 
-  err = http_open (r_hd, HTTP_REQ_GET, document, auth, flags,
+  err = http_open (r_hd, HTTP_REQ_GET, document, NULL, auth, flags,
                    proxy, session, srvtag, headers);
   if (err)
     return err;
@@ -1353,7 +1356,7 @@ parse_tuple (char *string)
  * Returns 0 if the request was successful
  */
 static gpg_error_t
-send_request (http_t hd, const char *auth,
+send_request (http_t hd, const char *httphost, const char *auth,
 	      const char *proxy, const char *srvtag, strlist_t headers)
 {
   gpg_error_t err;
@@ -1389,7 +1392,7 @@ send_request (http_t hd, const char *auth,
       int rc;
 
       xfree (hd->session->servername);
-      hd->session->servername = xtrystrdup (server);
+      hd->session->servername = xtrystrdup (httphost? httphost : server);
       if (!hd->session->servername)
         {
           err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
@@ -1549,11 +1552,13 @@ send_request (http_t hd, const char *auth,
   if (http_proxy && *http_proxy)
     {
       request = es_asprintf
-        ("%s http://%s:%hu%s%s HTTP/1.0\r\n%s%s",
+        ("%s %s://%s:%hu%s%s HTTP/1.0\r\n%s%s",
          hd->req_type == HTTP_REQ_GET ? "GET" :
          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
-         server, port, *p == '/' ? "" : "/", p,
+         hd->uri->use_tls? "https" : "http",
+         httphost? httphost : server,
+         port, *p == '/' ? "" : "/", p,
          authstr ? authstr : "",
          proxy_authstr ? proxy_authstr : "");
     }
@@ -1571,7 +1576,9 @@ send_request (http_t hd, const char *auth,
          hd->req_type == HTTP_REQ_GET ? "GET" :
          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
-         *p == '/' ? "" : "/", p, server, portstr,
+         *p == '/' ? "" : "/", p,
+         httphost? httphost : server,
+         portstr,
          authstr? authstr:"");
     }
   xfree (p);
@@ -2442,6 +2449,7 @@ http_verify_server_credentials (http_session_t sess)
   const gnutls_datum_t *certlist;
   unsigned int certlistlen;
   gnutls_x509_crt_t cert;
+  gpg_error_t err = 0;
 
   sess->verify.done = 1;
   sess->verify.status = 0;
@@ -2458,27 +2466,35 @@ http_verify_server_credentials (http_session_t sess)
   if (rc)
     {
       log_error ("%s: %s\n", errprefix, gnutls_strerror (rc));
-      return gpg_error (GPG_ERR_GENERAL);
+      if (!err)
+        err = gpg_error (GPG_ERR_GENERAL);
     }
-  if (status)
+  else if (status)
     {
       log_error ("%s: status=0x%04x\n", errprefix, status);
       sess->verify.status = status;
-      return gpg_error (GPG_ERR_GENERAL);
+      if (!err)
+        err = gpg_error (GPG_ERR_GENERAL);
     }
 
   hostname = sess->servername;
   if (!hostname || !strchr (hostname, '.'))
     {
       log_error ("%s: %s\n", errprefix, "hostname missing");
-      return gpg_error (GPG_ERR_GENERAL);
+      if (!err)
+        err = gpg_error (GPG_ERR_GENERAL);
     }
 
   certlist = gnutls_certificate_get_peers (sess->tls_session, &certlistlen);
   if (!certlistlen)
     {
       log_error ("%s: %s\n", errprefix, "server did not send a certificate");
-      return gpg_error (GPG_ERR_GENERAL);
+      if (!err)
+        err = gpg_error (GPG_ERR_GENERAL);
+
+      /* Need to stop here.  */
+      if (err)
+        return err;
     }
 
   /* log_debug ("Server sent %u certs\n", certlistlen); */
@@ -2502,7 +2518,10 @@ http_verify_server_credentials (http_session_t sess)
   rc = gnutls_x509_crt_init (&cert);
   if (rc < 0)
     {
-      return gpg_error (GPG_ERR_GENERAL);
+      if (!err)
+        err = gpg_error (GPG_ERR_GENERAL);
+      if (err)
+        return err;
     }
 
   rc = gnutls_x509_crt_import (cert, &certlist[0], GNUTLS_X509_FMT_DER);
@@ -2510,20 +2529,22 @@ http_verify_server_credentials (http_session_t sess)
     {
       log_error ("%s: %s: %s\n", errprefix, "error importing certificate",
                  gnutls_strerror (rc));
-      gnutls_x509_crt_deinit (cert);
-      return gpg_error (GPG_ERR_GENERAL);
+      if (!err)
+        err = gpg_error (GPG_ERR_GENERAL);
     }
 
   if (!gnutls_x509_crt_check_hostname (cert, hostname))
     {
       log_error ("%s: %s\n", errprefix, "hostname does not match");
-      gnutls_x509_crt_deinit (cert);
-      return gpg_error (GPG_ERR_GENERAL);
+      log_info ("(expected '%s')\n", hostname);
+      if (!err)
+        err = gpg_error (GPG_ERR_GENERAL);
     }
 
   gnutls_x509_crt_deinit (cert);
-  sess->verify.rc = 0;
-  return 0;  /* Verification succeeded.  */
+  if (!err)
+    sess->verify.rc = 0;
+  return err;
 #else /*!HTTP_USE_GNUTLS*/
   (void)sess;
   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
diff --git a/common/http.h b/common/http.h
index b6471b6..acfdc0f 100644
--- a/common/http.h
+++ b/common/http.h
@@ -110,6 +110,7 @@ gpg_error_t http_raw_connect (http_t *r_hd,
 
 gpg_error_t http_open (http_t *r_hd, http_req_t reqtype,
                        const char *url,
+                       const char *httphost,
                        const char *auth,
                        unsigned int flags,
                        const char *proxy,
diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
index 8c3384d..541c46f 100644
--- a/dirmngr/ks-engine-hkp.c
+++ b/dirmngr/ks-engine-hkp.c
@@ -765,6 +765,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
   err = http_open (&http,
                    post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
                    request,
+                   NULL,
                    /* fixme: AUTH */ NULL,
                    httpflags,
                    /* fixme: proxy*/ NULL,
diff --git a/dirmngr/ks-engine-http.c b/dirmngr/ks-engine-http.c
index a9399a1..aed3aaa 100644
--- a/dirmngr/ks-engine-http.c
+++ b/dirmngr/ks-engine-http.c
@@ -68,6 +68,7 @@ ks_http_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp)
   err = http_open (&http,
                    HTTP_REQ_GET,
                    url,
+                   /* httphost */ NULL,
                    /* fixme: AUTH */ NULL,
                    0,
                    /* fixme: proxy*/ NULL,
diff --git a/dirmngr/ocsp.c b/dirmngr/ocsp.c
index b941b5c..0d506ef 100644
--- a/dirmngr/ocsp.c
+++ b/dirmngr/ocsp.c
@@ -165,7 +165,7 @@ do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md,
     }
 
  once_more:
-  err = http_open (&http, HTTP_REQ_POST, url, NULL,
+  err = http_open (&http, HTTP_REQ_POST, url, NULL, NULL,
                    (opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0),
                    opt.http_proxy, NULL, NULL, NULL);
   if (err)
diff --git a/dirmngr/server.c b/dirmngr/server.c
index bdfb755..6cf4dd6 100644
--- a/dirmngr/server.c
+++ b/dirmngr/server.c
@@ -298,7 +298,7 @@ skip_options (char *line)
 }
 
 
-/* Return an error if the assuan context does not belong to teh owner
+/* Return an error if the assuan context does not belong to the owner
    of the process or to root.  On error FAILTEXT is set as Assuan
    error string.  */
 static gpg_error_t
diff --git a/keyserver/curl-shim.c b/keyserver/curl-shim.c
index 500d9f5..696efe2 100644
--- a/keyserver/curl-shim.c
+++ b/keyserver/curl-shim.c
@@ -198,7 +198,7 @@ curl_easy_perform(CURL *curl)
 
   if(curl->flags.post)
     {
-      rc = http_open (&curl->hd, HTTP_REQ_POST, curl->url, curl->auth,
+      rc = http_open (&curl->hd, HTTP_REQ_POST, curl->url, NULL, curl->auth,
                       0, proxy, NULL, curl->srvtag,
 		      curl->headers?curl->headers->list:NULL);
       if (!rc)
@@ -222,7 +222,7 @@ curl_easy_perform(CURL *curl)
     }
   else
     {
-      rc = http_open (&curl->hd, HTTP_REQ_GET, curl->url, curl->auth,
+      rc = http_open (&curl->hd, HTTP_REQ_GET, curl->url, NULL, curl->auth,
                       0, proxy, NULL, curl->srvtag,
 		      curl->headers?curl->headers->list:NULL);
       if (!rc)
@@ -282,7 +282,7 @@ curl_easy_perform(CURL *curl)
       err=CURLE_COULDNT_CONNECT;
       break;
     }
-      
+
   return handle_error(curl,err,errstr);
 }
 

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

Summary of changes:
 common/http.c            |   67 ++++++++----
 common/http.h            |    1 +
 dirmngr/ks-engine-hkp.c  |  269 +++++++++++++++++++++++++++++++++++-----------
 dirmngr/ks-engine-http.c |    1 +
 dirmngr/ocsp.c           |    2 +-
 dirmngr/server.c         |    2 +-
 keyserver/curl-shim.c    |    6 +-
 7 files changed, 260 insertions(+), 88 deletions(-)


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




More information about the Gnupg-commits mailing list