[Pkg-gnupg-commit] [gnupg2] 01/02: pull fixes from upstream (including a double-free in gpg-agent)

Daniel Kahn Gillmor dkg at fifthhorseman.net
Wed Jan 25 14:45:29 UTC 2017


This is an automated email from the git hooks/post-receive script.

dkg pushed a commit to branch master
in repository gnupg2.

commit 8a032314b092bc35426e3a8cf580c25f329f7f3e
Author: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
Date:   Wed Jan 25 09:29:14 2017 -0500

    pull fixes from upstream (including a double-free in gpg-agent)
---
 debian/patches/0012-tools-Fix-memory-leak.patch    |  28 +++
 .../0013-tools-Improve-error-handling.patch        |  29 +++
 .../0014-dirmngr-New-option-disable-ipv4.patch     | 245 ++++++++++++++++++++
 ...gr-Simplify-error-returning-inside-http.c.patch | 255 +++++++++++++++++++++
 .../0016-gpg-Print-a-warning-on-Tor-problems.patch | 188 +++++++++++++++
 debian/patches/0017-agent-Fix-double-free.patch    |  49 ++++
 debian/patches/series                              |   6 +
 7 files changed, 800 insertions(+)

diff --git a/debian/patches/0012-tools-Fix-memory-leak.patch b/debian/patches/0012-tools-Fix-memory-leak.patch
new file mode 100644
index 0000000..4d47557
--- /dev/null
+++ b/debian/patches/0012-tools-Fix-memory-leak.patch
@@ -0,0 +1,28 @@
+From: Justus Winter <justus at g10code.com>
+Date: Mon, 23 Jan 2017 11:52:30 +0100
+Subject: tools: Fix memory leak.
+
+* tools/gpgconf-comp.c (change_options_file): Fix leak.
+--
+Previously, 'src_filename' and 'orig_filename' leaked if creating the
+backup file failed.
+
+Signed-off-by: Justus Winter <justus at g10code.com>
+(cherry picked from commit 5b28f025085b386e0ec49535d4cd3f875a414eb0)
+---
+ tools/gpgconf-comp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
+index a25b5136e..85eb80ab5 100644
+--- a/tools/gpgconf-comp.c
++++ b/tools/gpgconf-comp.c
+@@ -2641,6 +2641,8 @@ change_options_file (gc_component_t component, gc_backend_t backend,
+   if (res < 0 && errno != ENOENT)
+     {
+       xfree (dest_filename);
++      xfree (src_filename);
++      xfree (orig_filename);
+       return -1;
+     }
+   if (res < 0)
diff --git a/debian/patches/0013-tools-Improve-error-handling.patch b/debian/patches/0013-tools-Improve-error-handling.patch
new file mode 100644
index 0000000..b0034da
--- /dev/null
+++ b/debian/patches/0013-tools-Improve-error-handling.patch
@@ -0,0 +1,29 @@
+From: Justus Winter <justus at g10code.com>
+Date: Mon, 23 Jan 2017 14:24:22 +0100
+Subject: tools: Improve error handling.
+
+* tools/gpgconf-comp.c (gp_component_change_options): Improve error
+handling when reading from stdin.
+--
+Previously, errors encountered while reading the configuration changes
+were ignored.
+
+Signed-off-by: Justus Winter <justus at g10code.com>
+(cherry picked from commit b0348fdb26637b0bcbd68a96c1746a1613b309af)
+---
+ tools/gpgconf-comp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
+index 85eb80ab5..180fd65c2 100644
+--- a/tools/gpgconf-comp.c
++++ b/tools/gpgconf-comp.c
+@@ -3328,6 +3328,8 @@ gc_component_change_options (int component, estream_t in, estream_t out,
+ 
+           change_one_value (option, runtime, flags, new_value, 0);
+         }
++      if (length < 0 || gpgrt_ferror (in))
++	gc_error (1, errno, "error reading stream 'in'");
+     }
+ 
+   /* Now that we have collected and locally verified the changes,
diff --git a/debian/patches/0014-dirmngr-New-option-disable-ipv4.patch b/debian/patches/0014-dirmngr-New-option-disable-ipv4.patch
new file mode 100644
index 0000000..ad0fb58
--- /dev/null
+++ b/debian/patches/0014-dirmngr-New-option-disable-ipv4.patch
@@ -0,0 +1,245 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Tue, 24 Jan 2017 16:36:28 +0100
+Subject: dirmngr: New option --disable-ipv4.
+
+* dirmngr/dirmngr.c (oDisableIPv4): New const.
+(opts): New option --disable-ipv4.
+(parse_rereadable_options): Set that option.
+* dirmngr/dirmngr.h (opt): New field 'disable_ipv4'.
+* dirmngr/dns-stuff.c (opt_disable_ipv4): bew var.
+(set_dns_disable_ipv4): New.
+(resolve_name_standard): Skip v4 addresses when OPT_DISABLE_IPV4 is
+set.
+* dirmngr/ks-engine-hkp.c (map_host): Ditto.
+(send_request): Pass HTTP_FLAG_IGNORE_IPv4 if opt.disable_v4 is set.
+* dirmngr/crlfetch.c (crl_fetch): Ditto.
+* dirmngr/ks-engine-finger.c (ks_finger_fetch): Ditto.
+* dirmngr/ks-engine-http.c (ks_http_fetch): Ditto.
+* dirmngr/ocsp.c (do_ocsp_request): Ditto.
+
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 72736af86a501592d974d46ff754a63959e183bd)
+---
+ dirmngr/crlfetch.c         |  4 +++-
+ dirmngr/dirmngr.c          |  5 +++++
+ dirmngr/dirmngr.h          |  1 +
+ dirmngr/dns-stuff.c        | 15 +++++++++++++++
+ dirmngr/dns-stuff.h        |  4 ++++
+ dirmngr/ks-engine-finger.c |  4 +++-
+ dirmngr/ks-engine-hkp.c    |  8 ++++++--
+ dirmngr/ks-engine-http.c   |  3 ++-
+ dirmngr/ocsp.c             |  3 ++-
+ doc/dirmngr.texi           |  5 +++++
+ 10 files changed, 46 insertions(+), 6 deletions(-)
+
+diff --git a/dirmngr/crlfetch.c b/dirmngr/crlfetch.c
+index 8fe6e0b1b..aa82137f7 100644
+--- a/dirmngr/crlfetch.c
++++ b/dirmngr/crlfetch.c
+@@ -198,7 +198,9 @@ crl_fetch (ctrl_t ctrl, const char *url, ksba_reader_t *reader)
+         err = http_open_document (&hd, url, NULL,
+                                   ((opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
+                                    |(DBG_LOOKUP? HTTP_FLAG_LOG_RESP:0)
+-                                   |(opt.use_tor? HTTP_FLAG_FORCE_TOR:0)),
++                                   |(opt.use_tor? HTTP_FLAG_FORCE_TOR:0)
++                                   |(opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4:0)
++                                   ),
+                                   ctrl->http_proxy, NULL, NULL, NULL);
+ 
+       switch ( err? 99999 : http_get_status_code (hd) )
+diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
+index 8d9de9e5a..83356c94c 100644
+--- a/dirmngr/dirmngr.c
++++ b/dirmngr/dirmngr.c
+@@ -111,6 +111,7 @@ enum cmd_and_opt_values {
+   oBatch,
+   oDisableHTTP,
+   oDisableLDAP,
++  oDisableIPv4,
+   oIgnoreLDAPDP,
+   oIgnoreHTTPDP,
+   oIgnoreOCSPSvcUrl,
+@@ -224,6 +225,8 @@ static ARGPARSE_OPTS opts[] = {
+ 
+   ARGPARSE_s_n (oUseTor, "use-tor", N_("route all network traffic via Tor")),
+ 
++  ARGPARSE_s_n (oDisableIPv4, "disable-ipv4", "@"),
++
+   ARGPARSE_s_s (oSocketName, "socket-name", "@"),  /* Only for debugging.  */
+ 
+   ARGPARSE_s_u (oFakedSystemTime, "faked-system-time", "@"), /*(epoch time)*/
+@@ -586,6 +589,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
+ 
+     case oDisableHTTP: opt.disable_http = 1; break;
+     case oDisableLDAP: opt.disable_ldap = 1; break;
++    case oDisableIPv4: opt.disable_ipv4 = 1; break;
+     case oHonorHTTPProxy: opt.honor_http_proxy = 1; break;
+     case oHTTPProxy: opt.http_proxy = pargs->r.ret_str; break;
+     case oLDAPProxy: opt.ldap_proxy = pargs->r.ret_str; break;
+@@ -645,6 +649,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
+ 
+   set_dns_verbose (opt.verbose, !!DBG_DNS);
+   http_set_verbose (opt.verbose, !!DBG_NETWORK);
++  set_dns_disable_ipv4 (opt.disable_ipv4);
+ 
+   return 1; /* Handled. */
+ }
+diff --git a/dirmngr/dirmngr.h b/dirmngr/dirmngr.h
+index acd4c636d..fd80d7237 100644
+--- a/dirmngr/dirmngr.h
++++ b/dirmngr/dirmngr.h
+@@ -98,6 +98,7 @@ struct
+ 
+   int disable_http;       /* Do not use HTTP at all.  */
+   int disable_ldap;       /* Do not use LDAP at all.  */
++  int disable_ipv4;       /* Do not use leagacy IP addresses.  */
+   int honor_http_proxy;   /* Honor the http_proxy env variable. */
+   const char *http_proxy; /* The default HTTP proxy.  */
+   const char *ldap_proxy; /* Use given LDAP proxy.  */
+diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c
+index 9347196b3..ad19fc2ce 100644
+--- a/dirmngr/dns-stuff.c
++++ b/dirmngr/dns-stuff.c
+@@ -119,6 +119,10 @@ static int opt_debug;
+ /* The timeout in seconds for libdns requests.  */
+ static int opt_timeout;
+ 
++/* The flag to disable IPv4 access - right now this only skips
++ * returned A records.  */
++static int opt_disable_ipv4;
++
+ /* If set force the use of the standard resolver.  */
+ static int standard_resolver;
+ 
+@@ -227,6 +231,15 @@ set_dns_verbose (int verbose, int debug)
+ }
+ 
+ 
++/* Set the Disable-IPv4 flag so that the name resolver does not return
++ * A addresses.  */
++void
++set_dns_disable_ipv4 (int yes)
++{
++  opt_disable_ipv4 = !!yes;
++}
++
++
+ /* Set the timeout for libdns requests to SECONDS.  A value of 0 sets
+  * the default timeout and values are capped at 10 minutes.  */
+ void
+@@ -873,6 +886,8 @@ resolve_name_standard (const char *name, unsigned short port,
+     {
+       if (ai->ai_family != AF_INET6 && ai->ai_family != AF_INET)
+         continue;
++      if (opt_disable_ipv4 && ai->ai_family == AF_INET)
++        continue;
+ 
+       dai = xtrymalloc (sizeof *dai + ai->ai_addrlen - 1);
+       dai->family = ai->ai_family;
+diff --git a/dirmngr/dns-stuff.h b/dirmngr/dns-stuff.h
+index d68dd1728..9eb97fd6a 100644
+--- a/dirmngr/dns-stuff.h
++++ b/dirmngr/dns-stuff.h
+@@ -95,6 +95,10 @@ struct srventry
+ /* Set verbosity and debug mode for this module. */
+ void set_dns_verbose (int verbose, int debug);
+ 
++/* Set the Disable-IPv4 flag so that the name resolver does not return
++ * A addresses.  */
++void set_dns_disable_ipv4 (int yes);
++
+ /* Set the timeout for libdns requests to SECONDS.  */
+ void set_dns_timeout (int seconds);
+ 
+diff --git a/dirmngr/ks-engine-finger.c b/dirmngr/ks-engine-finger.c
+index b1f02ad7d..114f2e9ac 100644
+--- a/dirmngr/ks-engine-finger.c
++++ b/dirmngr/ks-engine-finger.c
+@@ -83,7 +83,9 @@ ks_finger_fetch (ctrl_t ctrl, parsed_uri_t uri, estream_t *r_fp)
+   *server++ = 0;
+ 
+   err = http_raw_connect (&http, server, 79,
+-                          (opt.use_tor? HTTP_FLAG_FORCE_TOR : 0), NULL);
++                          ((opt.use_tor? HTTP_FLAG_FORCE_TOR : 0)
++                           | (opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)),
++                          NULL);
+   if (err)
+     {
+       xfree (name);
+diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
+index 2b90441e2..dad83efcd 100644
+--- a/dirmngr/ks-engine-hkp.c
++++ b/dirmngr/ks-engine-hkp.c
+@@ -526,6 +526,8 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
+             {
+               if (ai->family != AF_INET && ai->family != AF_INET6)
+                 continue;
++              if (opt.disable_ipv4 && ai->family == AF_INET)
++                continue;
+               dirmngr_tick (ctrl);
+ 
+               add_host (name, is_pool, ai, 0, reftbl, reftblsize, &refidx);
+@@ -607,7 +609,8 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
+         {
+           for (ai = aibuf; ai; ai = ai->next)
+             {
+-              if (ai->family == AF_INET6 || ai->family == AF_INET)
++              if (ai->family == AF_INET6
++                  || (!opt.disable_ipv4 && ai->family == AF_INET))
+                 {
+                   err = resolve_dns_addr (ai->addr, ai->addrlen, 0, &host);
+                   if (!err)
+@@ -1058,7 +1061,8 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
+                    /* fixme: AUTH */ NULL,
+                    (httpflags
+                     |(opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
+-                    |(opt.use_tor? HTTP_FLAG_FORCE_TOR:0)),
++                    |(opt.use_tor? HTTP_FLAG_FORCE_TOR:0)
++                    |(opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)),
+                    ctrl->http_proxy,
+                    session,
+                    NULL,
+diff --git a/dirmngr/ks-engine-http.c b/dirmngr/ks-engine-http.c
+index 858c943ea..dbbf4bb79 100644
+--- a/dirmngr/ks-engine-http.c
++++ b/dirmngr/ks-engine-http.c
+@@ -88,7 +88,8 @@ ks_http_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp)
+                    /* httphost */ NULL,
+                    /* fixme: AUTH */ NULL,
+                    ((opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
+-                    | (opt.use_tor? HTTP_FLAG_FORCE_TOR:0)),
++                    | (opt.use_tor? HTTP_FLAG_FORCE_TOR:0)
++                    | (opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)),
+                    ctrl->http_proxy,
+                    session,
+                    NULL,
+diff --git a/dirmngr/ocsp.c b/dirmngr/ocsp.c
+index 9127cf754..b46c78567 100644
+--- a/dirmngr/ocsp.c
++++ b/dirmngr/ocsp.c
+@@ -174,7 +174,8 @@ 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, NULL,
+                    ((opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
+-                    | (opt.use_tor? HTTP_FLAG_FORCE_TOR:0)),
++                    | (opt.use_tor? HTTP_FLAG_FORCE_TOR:0)
++                    | (opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)),
+                    ctrl->http_proxy, NULL, NULL, NULL);
+   if (err)
+     {
+diff --git a/doc/dirmngr.texi b/doc/dirmngr.texi
+index e27157c00..fcc174f92 100644
+--- a/doc/dirmngr.texi
++++ b/doc/dirmngr.texi
+@@ -313,6 +313,11 @@ not be used a different one can be given using this option.  Note that
+ a numerical IP address must be given (IPv6 or IPv4) and that no error
+ checking is done for @var{ipaddr}.
+ 
++ at item --disable-ipv4
++ at opindex disable-ipv4
++Disable the use of all IPv4 addresses.  This option is mainly useful
++for debugging.
++
+ @item --disable-ldap
+ @opindex disable-ldap
+ Entirely disables the use of LDAP.
diff --git a/debian/patches/0015-dirmngr-Simplify-error-returning-inside-http.c.patch b/debian/patches/0015-dirmngr-Simplify-error-returning-inside-http.c.patch
new file mode 100644
index 0000000..bcf4ee6
--- /dev/null
+++ b/debian/patches/0015-dirmngr-Simplify-error-returning-inside-http.c.patch
@@ -0,0 +1,255 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Tue, 24 Jan 2017 18:41:43 +0100
+Subject: dirmngr: Simplify error returning inside http.c.
+
+* dirmngr/http.c (connect_server): Change to return an gpg_error_t
+and to store socket at the passed address.
+(http_raw_connect, send_request): Adjust accordingly.
+--
+
+This change removes cruft from the code and allows to return the error
+code from the name lookup.
+
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 51e5a5e5a46279809848b4ab4419f35045336010)
+---
+ dirmngr/http.c | 101 ++++++++++++++++++++++++++++-----------------------------
+ 1 file changed, 50 insertions(+), 51 deletions(-)
+
+diff --git a/dirmngr/http.c b/dirmngr/http.c
+index 35877d241..fe9c3c734 100644
+--- a/dirmngr/http.c
++++ b/dirmngr/http.c
+@@ -155,9 +155,9 @@ static gpg_error_t send_request (http_t hd, const char *httphost,
+ static char *build_rel_path (parsed_uri_t uri);
+ static gpg_error_t parse_response (http_t hd);
+ 
+-static assuan_fd_t connect_server (const char *server, unsigned short port,
++static gpg_error_t connect_server (const char *server, unsigned short port,
+                                    unsigned int flags, const char *srvtag,
+-                                   int *r_host_not_found);
++                                   assuan_fd_t *r_sock);
+ static gpg_error_t write_server (int sock, const char *data, size_t length);
+ 
+ static gpgrt_ssize_t cookie_read (void *cookie, void *buffer, size_t size);
+@@ -924,7 +924,6 @@ http_raw_connect (http_t *r_hd, const char *server, unsigned short port,
+   gpg_error_t err = 0;
+   http_t hd;
+   cookie_t cookie;
+-  int hnf;
+ 
+   *r_hd = NULL;
+ 
+@@ -950,12 +949,9 @@ http_raw_connect (http_t *r_hd, const char *server, unsigned short port,
+   {
+     assuan_fd_t sock;
+ 
+-    sock = connect_server (server, port, hd->flags, srvtag, &hnf);
+-    if (sock == ASSUAN_INVALID_FD)
++    err = connect_server (server, port, hd->flags, srvtag, &sock);
++    if (err)
+       {
+-        err = gpg_err_make (default_errsource,
+-                            (hnf? GPG_ERR_UNKNOWN_HOST
+-                             : gpg_err_code_from_syserror ()));
+         xfree (hd);
+         return err;
+       }
+@@ -1643,7 +1639,6 @@ send_request (http_t hd, const char *httphost, const char *auth,
+   char *proxy_authstr = NULL;
+   char *authstr = NULL;
+   int sock;
+-  int hnf;
+ 
+   if (hd->uri->use_tls && !hd->session)
+     {
+@@ -1713,7 +1708,6 @@ send_request (http_t hd, const char *httphost, const char *auth,
+             && *http_proxy ))
+     {
+       parsed_uri_t uri;
+-      int save_errno;
+ 
+       if (proxy)
+ 	http_proxy = proxy;
+@@ -1760,25 +1754,20 @@ send_request (http_t hd, const char *httphost, const char *auth,
+             }
+         }
+ 
+-      sock = connect_server (*uri->host ? uri->host : "localhost",
+-                             uri->port ? uri->port : 80,
+-                             hd->flags, srvtag, &hnf);
+-      save_errno = errno;
++      err = connect_server (*uri->host ? uri->host : "localhost",
++                            uri->port ? uri->port : 80,
++                            hd->flags, srvtag, &sock);
+       http_release_parsed_uri (uri);
+-      if (sock == ASSUAN_INVALID_FD)
+-        gpg_err_set_errno (save_errno);
+     }
+   else
+     {
+-      sock = connect_server (server, port, hd->flags, srvtag, &hnf);
++      err = connect_server (server, port, hd->flags, srvtag, &sock);
+     }
+ 
+-  if (sock == ASSUAN_INVALID_FD)
++  if (err)
+     {
+       xfree (proxy_authstr);
+-      return gpg_err_make (default_errsource,
+-                           (hnf? GPG_ERR_UNKNOWN_HOST
+-                               : gpg_err_code_from_syserror ()));
++      return err;
+     }
+   hd->sock = my_socket_new (sock);
+   if (!hd->sock)
+@@ -1788,7 +1777,6 @@ send_request (http_t hd, const char *httphost, const char *auth,
+     }
+ 
+ 
+-
+ #if HTTP_USE_NTBTLS
+   if (hd->uri->use_tls)
+     {
+@@ -2476,11 +2464,13 @@ my_sock_new_for_addr (struct sockaddr *addr, int type, int proto)
+ }
+ 
+ 
+-/* Actually connect to a server.  Returns the file descriptor or -1 on
+-   error.  ERRNO is set on error. */
+-static assuan_fd_t
++/* Actually connect to a server.  On success 0 is returned and the
++ * file descriptor for the socket is stored at R_SOCK; on error an
++ * error code is returned and ASSUAN_INVALID_FD is stored at
++ * R_SOCK.  */
++static gpg_error_t
+ connect_server (const char *server, unsigned short port,
+-                unsigned int flags, const char *srvtag, int *r_host_not_found)
++                unsigned int flags, const char *srvtag, assuan_fd_t *r_sock)
+ {
+   gpg_error_t err;
+   assuan_fd_t sock = ASSUAN_INVALID_FD;
+@@ -2488,11 +2478,11 @@ connect_server (const char *server, unsigned short port,
+   int hostfound = 0;
+   int anyhostaddr = 0;
+   int srv, connected;
+-  int last_errno = 0;
++  gpg_error_t last_err = 0;
+   struct srventry *serverlist = NULL;
+-  int ret;
+ 
+-  *r_host_not_found = 0;
++  *r_sock = ASSUAN_INVALID_FD;
++
+ #if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP)
+   init_sockets ();
+ #endif /*Windows*/
+@@ -2509,18 +2499,21 @@ connect_server (const char *server, unsigned short port,
+                                          ASSUAN_SOCK_TOR);
+       if (sock == ASSUAN_INVALID_FD)
+         {
+-          if (errno == EHOSTUNREACH)
+-            *r_host_not_found = 1;
+-          log_error ("can't connect to '%s': %s\n", server, strerror (errno));
++          err = gpg_err_make (default_errsource,
++                              (errno == EHOSTUNREACH)? GPG_ERR_UNKNOWN_HOST
++                              : gpg_err_code_from_syserror ());
++          log_error ("can't connect to '%s': %s\n", server, gpg_strerror (err));
++          return err;
+         }
+-      else
+-        notify_netactivity ();
+-      return sock;
++
++      notify_netactivity ();
++      *r_sock = sock;
++      return 0;
+ 
+ #else /*!ASSUAN_SOCK_TOR*/
+ 
+-      gpg_err_set_errno (ENETUNREACH);
+-      return -1; /* Out of core.  */
++      err = gpg_err_make (default_errsource, GPG_ERR_ENETUNREACH);
++      return ASSUAN_INVALID_FD;
+ 
+ #endif /*!HASSUAN_SOCK_TOR*/
+     }
+@@ -2533,6 +2526,7 @@ connect_server (const char *server, unsigned short port,
+         log_info ("getting '%s' SRV for '%s' failed: %s\n",
+                   srvtag, server, gpg_strerror (err));
+       /* Note that on error SRVCOUNT is zero.  */
++      err = 0;
+     }
+ 
+   if (!serverlist)
+@@ -2541,7 +2535,8 @@ connect_server (const char *server, unsigned short port,
+ 	 up a fake SRV record. */
+       serverlist = xtrycalloc (1, sizeof *serverlist);
+       if (!serverlist)
+-        return -1; /* Out of core.  */
++        return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
++
+       serverlist->port = port;
+       strncpy (serverlist->target, server, DIMof (struct srventry, target));
+       serverlist->target[DIMof (struct srventry, target)-1] = '\0';
+@@ -2562,6 +2557,7 @@ connect_server (const char *server, unsigned short port,
+         {
+           log_info ("resolving '%s' failed: %s\n",
+                     serverlist[srv].target, gpg_strerror (err));
++          last_err = err;
+           continue; /* Not found - try next one. */
+         }
+       hostfound = 1;
+@@ -2578,18 +2574,20 @@ connect_server (const char *server, unsigned short port,
+           sock = my_sock_new_for_addr (ai->addr, ai->socktype, ai->protocol);
+           if (sock == ASSUAN_INVALID_FD)
+             {
+-              int save_errno = errno;
+-              log_error ("error creating socket: %s\n", strerror (errno));
++              err = gpg_err_make (default_errsource,
++                                  gpg_err_code_from_syserror ());
++              log_error ("error creating socket: %s\n", gpg_strerror (err));
+               free_dns_addrinfo (aibuf);
+               xfree (serverlist);
+-              errno = save_errno;
+-              return ASSUAN_INVALID_FD;
++              return err;
+             }
+ 
+           anyhostaddr = 1;
+-          ret = assuan_sock_connect (sock, ai->addr, ai->addrlen);
+-          if (ret)
+-            last_errno = errno;
++          if (assuan_sock_connect (sock, ai->addr, ai->addrlen))
++            {
++              last_err = gpg_err_make (default_errsource,
++                                       gpg_err_code_from_syserror ());
++            }
+           else
+             {
+               connected = 1;
+@@ -2616,17 +2614,18 @@ connect_server (const char *server, unsigned short port,
+                    server, (int)WSAGetLastError());
+ #else
+         log_error ("can't connect to '%s': %s\n",
+-                   server, strerror (last_errno));
++                   server, gpg_strerror (last_err));
+ #endif
+         }
+-      if (!hostfound || (hostfound && !anyhostaddr))
+-        *r_host_not_found = 1;
++      err = last_err? last_err : gpg_err_make (default_errsource,
++                                               GPG_ERR_UNKNOWN_HOST);
+       if (sock != ASSUAN_INVALID_FD)
+ 	assuan_sock_close (sock);
+-      gpg_err_set_errno (last_errno);
+-      return ASSUAN_INVALID_FD;
++      return err;
+     }
+-  return sock;
++
++  *r_sock = sock;
++  return 0;
+ }
+ 
+ 
diff --git a/debian/patches/0016-gpg-Print-a-warning-on-Tor-problems.patch b/debian/patches/0016-gpg-Print-a-warning-on-Tor-problems.patch
new file mode 100644
index 0000000..1979069
--- /dev/null
+++ b/debian/patches/0016-gpg-Print-a-warning-on-Tor-problems.patch
@@ -0,0 +1,188 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Tue, 24 Jan 2017 20:45:31 +0100
+Subject: gpg: Print a warning on Tor problems.
+
+* dirmngr/ks-engine-hkp.c (tor_not_running_p): New.
+(map_host): Call that to print a warning.
+(handle_send_request_error): Ditto and avoid marking the host dead.
+Also print a tor_config_problem warning.  Add arg CTRL; adjust callers
+to pass that new arg.
+* g10/call-dirmngr.c (ks_status_cb): Detect and print the new
+warnings.
+
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 770b75a746836773909af25ccb9b480e61cea677)
+---
+ dirmngr/ks-engine-hkp.c | 60 ++++++++++++++++++++++++++++++++++++-------------
+ g10/call-dirmngr.c      | 26 ++++++++++++++++++++-
+ 2 files changed, 70 insertions(+), 16 deletions(-)
+
+diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
+index dad83efcd..858cd2f26 100644
+--- a/dirmngr/ks-engine-hkp.c
++++ b/dirmngr/ks-engine-hkp.c
+@@ -278,6 +278,31 @@ arecords_is_pool (dns_addrinfo_t aibuf)
+ }
+ 
+ 
++/* Print a warninng 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)
++{
++  assuan_fd_t sock;
++
++  if (!opt.use_tor)
++    return 0;
++
++  sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
++  if (sock != ASSUAN_INVALID_FD)
++    {
++      assuan_sock_close (sock);
++      return 0;
++    }
++
++  log_info ("(it seems Tor is not running)\n");
++  dirmngr_status (ctrl, "WARNING", "tor_not_running 0",
++                  "Tor is enabled but the local Tor daemon"
++                  " seems to be down", NULL);
++  return 1;
++}
++
++
+ /* 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
+@@ -475,6 +500,8 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
+           if (err)
+             {
+               xfree (reftbl);
++              if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
++                tor_not_running_p (ctrl);
+               return err;
+             }
+ 
+@@ -1180,13 +1207,13 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
+ }
+ 
+ 
+-/* Helper to evaluate the error code ERR form a send_request() call
++/* Helper to evaluate the error code ERR from a send_request() call
+    with REQUEST.  The function returns true if the caller shall try
+    again.  TRIES_LEFT points to a variable to track the number of
+    retries; this function decrements it and won't return true if it is
+    down to zero. */
+ static int
+-handle_send_request_error (gpg_error_t err, const char *request,
++handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
+                            unsigned int *tries_left)
+ {
+   int retry = 0;
+@@ -1197,16 +1224,9 @@ handle_send_request_error (gpg_error_t err, const char *request,
+   switch (gpg_err_code (err))
+     {
+     case GPG_ERR_ECONNREFUSED:
+-      if (opt.use_tor)
+-        {
+-          assuan_fd_t sock;
+-
+-          sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
+-          if (sock == ASSUAN_INVALID_FD)
+-            log_info ("(it seems Tor is not running)\n");
+-          else
+-            assuan_sock_close (sock);
+-        }
++      if (tor_not_running_p (ctrl))
++        break; /* A retry does not make sense.  */
++      /* Okay: Tor is up or --use-tor is not used.  */
+       /*FALLTHRU*/
+     case GPG_ERR_ENETUNREACH:
+     case GPG_ERR_ENETDOWN:
+@@ -1224,6 +1244,16 @@ handle_send_request_error (gpg_error_t err, const char *request,
+         }
+       break;
+ 
++    case GPG_ERR_EACCES:
++      if (opt.use_tor)
++        {
++          log_info ("(Tor configuration problem)\n");
++          dirmngr_status (ctrl, "WARNING", "tor_config_problem 0",
++                          "Please check that the \"SocksPort\" flag "
++                          "\"IPv6Traffic\" is set in torrc", NULL);
++        }
++      break;
++
+     default:
+       break;
+     }
+@@ -1334,7 +1364,7 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
+   /* Send the request.  */
+   err = send_request (ctrl, request, hostport, httphost, httpflags,
+                       NULL, NULL, &fp, r_http_status);
+-  if (handle_send_request_error (err, request, &tries))
++  if (handle_send_request_error (ctrl, err, request, &tries))
+     {
+       reselect = 1;
+       goto again;
+@@ -1468,7 +1498,7 @@ 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, httphost, httpflags,
+                       NULL, NULL, &fp, NULL);
+-  if (handle_send_request_error (err, request, &tries))
++  if (handle_send_request_error (ctrl, err, request, &tries))
+     {
+       reselect = 1;
+       goto again;
+@@ -1577,7 +1607,7 @@ 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, httphost, 0,
+                       put_post_cb, &parm, &fp, NULL);
+-  if (handle_send_request_error (err, request, &tries))
++  if (handle_send_request_error (ctrl, err, request, &tries))
+     {
+       reselect = 1;
+       goto again;
+diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c
+index 4be9da117..2f2ba982e 100644
+--- a/g10/call-dirmngr.c
++++ b/g10/call-dirmngr.c
+@@ -374,7 +374,8 @@ ks_status_cb (void *opaque, const char *line)
+ {
+   struct ks_status_parm_s *parm = opaque;
+   gpg_error_t err = 0;
+-  const char *s;
++  const char *s, *s2;
++  const char *warn;
+ 
+   if ((s = has_leading_keyword (line, parm->keyword? parm->keyword : "SOURCE")))
+     {
+@@ -385,6 +386,29 @@ ks_status_cb (void *opaque, const char *line)
+             err = gpg_error_from_syserror ();
+         }
+     }
++  else if ((s = has_leading_keyword (line, "WARNING")))
++    {
++      if ((s2 = has_leading_keyword (s, "tor_not_running")))
++        warn = _("Tor is not running");
++      else if ((s2 = has_leading_keyword (s, "tor_config_problem")))
++        warn = _("Tor is not properly configured");
++      else
++        warn = NULL;
++
++      if (warn)
++        {
++          log_info (_("WARNING: %s\n"), warn);
++          if (s2)
++            {
++              while (*s2 && !spacep (s2))
++                s2++;
++              while (*s2 && spacep (s2))
++                s2++;
++              if (*s2)
++                print_further_info ("%s", s2);
++            }
++        }
++    }
+ 
+   return err;
+ }
diff --git a/debian/patches/0017-agent-Fix-double-free.patch b/debian/patches/0017-agent-Fix-double-free.patch
new file mode 100644
index 0000000..b3d96ed
--- /dev/null
+++ b/debian/patches/0017-agent-Fix-double-free.patch
@@ -0,0 +1,49 @@
+From: Justus Winter <justus at g10code.com>
+Date: Wed, 25 Jan 2017 13:51:57 +0100
+Subject: agent: Fix double free.
+
+* agent/cache.c (agent_store_cache_hit): Make sure the update is
+atomic.
+--
+Previously, the function freed the last key, and duplicated the new
+key after doing that.  There is a chance, however, that calling the
+allocator surrenders control to a different thread, causing a double
+free if a different thread also calls this function.
+
+To make sure the update is atomic under the non-preemptive thread
+model, we must make sure not to surrender control to a different
+thread.  Therefore, we avoid calling the allocator during the
+update.
+
+Signed-off-by: Justus Winter <justus at g10code.com>
+(cherry picked from commit e175152ef7515921635bf1e00383e812668d13fc)
+---
+ agent/cache.c | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+diff --git a/agent/cache.c b/agent/cache.c
+index f58eaeaaa..248368277 100644
+--- a/agent/cache.c
++++ b/agent/cache.c
+@@ -475,6 +475,19 @@ agent_get_cache (const char *key, cache_mode_t cache_mode)
+ void
+ agent_store_cache_hit (const char *key)
+ {
+-  xfree (last_stored_cache_key);
+-  last_stored_cache_key = key? xtrystrdup (key) : NULL;
++  char *new;
++  char *old;
++
++  /* To make sure the update is atomic under the non-preemptive thread
++   * model, we must make sure not to surrender control to a different
++   * thread.  Therefore, we avoid calling the allocator during the
++   * update.  */
++  new = key ? xtrystrdup (key) : NULL;
++
++  /* Atomic update.  */
++  old = last_stored_cache_key;
++  last_stored_cache_key = new;
++  /* Done.  */
++
++  xfree (old);
+ }
diff --git a/debian/patches/series b/debian/patches/series
index a43241d..8ab8f62 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -9,3 +9,9 @@ gpg-agent-idling/0001-agent-Create-framework-of-scheduled-timers.patch
 gpg-agent-idling/0002-agent-Allow-threads-to-interrupt-main-select-loop-wi.patch
 gpg-agent-idling/0003-agent-Avoid-tight-timer-tick-when-possible.patch
 gpg-agent-idling/0004-agent-Avoid-scheduled-checks-on-socket-when-inotify-.patch
+0012-tools-Fix-memory-leak.patch
+0013-tools-Improve-error-handling.patch
+0014-dirmngr-New-option-disable-ipv4.patch
+0015-dirmngr-Simplify-error-returning-inside-http.c.patch
+0016-gpg-Print-a-warning-on-Tor-problems.patch
+0017-agent-Fix-double-free.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gnupg/gnupg2.git



More information about the Pkg-gnupg-commit mailing list