[pkg-gnupg-maint] Bug#863734: unblock: gnupg2/2.1.18-8

Daniel Kahn Gillmor dkg at fifthhorseman.net
Tue May 30 16:41:48 UTC 2017


Package: release.debian.org
Severity: normal
User: release.debian.org at packages.debian.org
Usertags: unblock
Control: affects -1 src:gnupg2

Please unblock package gnupg2

The gnupg2 source package 2.1.18-8 contains a significant number of
useful fixes from 2.1.18-6, and should be propagated into testing.

The fixes make the new package work better with smartcards, when some
signing keys are missing, and make it less likely for users to end up
with stale, unnecessary configuration files in future debian
installations.

Most fixes are all pulled from upstream to make it easier to integrate
future security patches, while avoiding major changes in underlying
behavior.

the bugs addressed include:
  #862032
  #854359
  #854829
  #834922
  #858082

This unblock would also address the concerns rasied around
win32-loader by odyx.

unblock gnupg2/2.1.18-8

-- System Information:
Debian Release: 9.0
  APT prefers testing-debug
  APT policy: (500, 'testing-debug'), (500, 'testing'), (200, 'unstable-debug'), (200, 'unstable'), (1, 'experimental-debug'), (1, 'experimental')
Architecture: amd64
 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.9.0-2-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
-------------- next part --------------
diff -Nru gnupg2-2.1.18/debian/changelog gnupg2-2.1.18/debian/changelog
--- gnupg2-2.1.18/debian/changelog	2017-02-13 19:29:34.000000000 -0500
+++ gnupg2-2.1.18/debian/changelog	2017-05-08 19:20:45.000000000 -0400
@@ -1,3 +1,19 @@
+gnupg2 (2.1.18-8) unstable; urgency=medium
+
+  * updated scdaemon fix from gniibe (Closes: #862032)
+
+ -- Daniel Kahn Gillmor <dkg at fifthhorseman.net>  Mon, 08 May 2017 19:20:45 -0400
+
+gnupg2 (2.1.18-7) unstable; urgency=medium
+
+  * scdaemon fixes from gniibe
+  * more upstream fixes (Closes: #854359, #854829)
+  * skip over missing signing keys (Closes: #834922)
+  * drop all skel files (Closes: #858082)
+  * Avoid spurious warnings when sharing a keybox with gpg >= 2.1.20
+
+ -- Daniel Kahn Gillmor <dkg at fifthhorseman.net>  Fri, 05 May 2017 23:06:48 -0400
+
 gnupg2 (2.1.18-6) unstable; urgency=medium
 
   [ NIIBE Yutaka ]
diff -Nru gnupg2-2.1.18/debian/dirmngr.install gnupg2-2.1.18/debian/dirmngr.install
--- gnupg2-2.1.18/debian/dirmngr.install	2017-02-08 19:44:24.000000000 -0500
+++ gnupg2-2.1.18/debian/dirmngr.install	2017-05-05 22:35:40.000000000 -0400
@@ -1,7 +1,6 @@
 debian/tmp/usr/bin/dirmngr
 debian/tmp/usr/bin/dirmngr-client
 debian/tmp/usr/lib/gnupg/dirmngr_ldap
-debian/tmp/usr/share/gnupg/dirmngr-conf.skel
 debian/tmp/usr/share/gnupg/sks-keyservers.netCA.pem
 doc/examples/systemd-user/dirmngr.service usr/lib/systemd/user
 doc/examples/systemd-user/dirmngr.socket usr/lib/systemd/user
diff -Nru gnupg2-2.1.18/debian/gnupg.install gnupg2-2.1.18/debian/gnupg.install
--- gnupg2-2.1.18/debian/gnupg.install	2017-02-08 19:44:24.000000000 -0500
+++ gnupg2-2.1.18/debian/gnupg.install	2017-05-05 22:35:40.000000000 -0400
@@ -9,5 +9,4 @@
 debian/tmp/usr/sbin/addgnupghome
 debian/tmp/usr/sbin/applygnupgdefaults
 debian/tmp/usr/share/gnupg/distsigkey.gpg
-debian/tmp/usr/share/gnupg/gpg-conf.skel
 tools/lspgpot usr/bin
diff -Nru gnupg2-2.1.18/debian/patches/0030-scd-Fix-factory-reset.patch gnupg2-2.1.18/debian/patches/0030-scd-Fix-factory-reset.patch
--- gnupg2-2.1.18/debian/patches/0030-scd-Fix-factory-reset.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0030-scd-Fix-factory-reset.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,367 @@
+From: NIIBE Yutaka <gniibe at fsij.org>
+Date: Fri, 17 Feb 2017 03:30:05 -0500
+Subject: scd: Fix factory-reset.
+
+Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>
+
+Backport from master branch:
+
+    99d4dfe83
+    e2792813a
+    031e3fa7b
+
+Additionally, fix another bug when tested with 2.1.18-7 with PC/SC.
+---
+ scd/app-common.h |  3 +-
+ scd/app.c        | 86 ++++++++++++++++++++++++++++++++------------------------
+ scd/command.c    |  6 ++--
+ scd/scdaemon.c   | 51 ++++++++++++++++++++++++++++++---
+ scd/scdaemon.h   |  1 +
+ 5 files changed, 102 insertions(+), 45 deletions(-)
+
+diff --git a/scd/app-common.h b/scd/app-common.h
+index b979f54..c7a0575 100644
+--- a/scd/app-common.h
++++ b/scd/app-common.h
+@@ -54,6 +54,7 @@ struct app_ctx_s {
+   const char *apptype;
+   unsigned int card_version;
+   unsigned int card_status;
++  unsigned int reset_requested:1;
+   unsigned int require_get_status:1;
+   unsigned int did_chv1:1;
+   unsigned int force_chv1:1;   /* True if the card does not cache CHV1. */
+@@ -134,7 +135,7 @@ gpg_error_t select_application (ctrl_t ctrl, const char *name, app_t *r_app,
+                                 int scan, const unsigned char *serialno_bin,
+                                 size_t serialno_bin_len);
+ char *get_supported_applications (void);
+-void release_application (app_t app);
++void release_application (app_t app, int locked_already);
+ gpg_error_t app_munge_serialno (app_t app);
+ gpg_error_t app_write_learn_status (app_t app, ctrl_t ctrl,
+                                     unsigned int flags);
+diff --git a/scd/app.c b/scd/app.c
+index 8fb0d45..3f3f3ef 100644
+--- a/scd/app.c
++++ b/scd/app.c
+@@ -136,40 +136,32 @@ check_application_conflict (const char *name, app_t app)
+ }
+ 
+ 
+-static void
+-release_application_internal (app_t app)
+-{
+-  if (!app->ref_count)
+-    log_bug ("trying to release an already released context\n");
+-
+-  --app->ref_count;
+-}
+-
+ gpg_error_t
+ app_reset (app_t app, ctrl_t ctrl, int send_reset)
+ {
+-  gpg_error_t err;
+-
+-  err = lock_app (app, ctrl);
+-  if (err)
+-    return err;
++  gpg_error_t err = 0;
+ 
+   if (send_reset)
+     {
+-      int sw = apdu_reset (app->slot);
++      int sw;
++
++      lock_app (app, ctrl);
++      sw = apdu_reset (app->slot);
+       if (sw)
+         err = gpg_error (GPG_ERR_CARD_RESET);
+ 
+-      /* Release the same application which is used by other sessions.  */
+-      send_client_notifications (app, 1);
++      app->reset_requested = 1;
++      unlock_app (app);
++
++      scd_kick_the_loop ();
++      gnupg_sleep (1);
+     }
+   else
+     {
+       ctrl->app_ctx = NULL;
+-      release_application_internal (app);
++      release_application (app, 0);
+     }
+ 
+-  unlock_app (app);
+   return err;
+ }
+ 
+@@ -370,6 +362,7 @@ select_application (ctrl_t ctrl, const char *name, app_t *r_app,
+         }
+ 
+       apdu_dev_list_finish (l);
++      scd_kick_the_loop ();
+     }
+ 
+   npth_mutex_lock (&app_list_lock);
+@@ -465,6 +458,8 @@ deallocate_app (app_t app)
+     }
+ 
+   xfree (app->serialno);
++
++  unlock_app (app);
+   xfree (app);
+ }
+ 
+@@ -474,7 +469,7 @@ deallocate_app (app_t app)
+    actually deferring the deallocation to allow for a later reuse by
+    a new connection. */
+ void
+-release_application (app_t app)
++release_application (app_t app, int locked_already)
+ {
+   if (!app)
+     return;
+@@ -484,9 +479,15 @@ release_application (app_t app)
+      is using the card - this way the PIN cache and other cached data
+      are preserved.  */
+ 
+-  lock_app (app, NULL);
+-  release_application_internal (app);
+-  unlock_app (app);
++  if (!locked_already)
++    lock_app (app, NULL);
++
++  if (!app->ref_count)
++    log_bug ("trying to release an already released context\n");
++
++  --app->ref_count;
++  if (!locked_already)
++    unlock_app (app);
+ }
+ 
+ 
+@@ -1023,11 +1024,16 @@ scd_update_reader_status_file (void)
+   npth_mutex_lock (&app_list_lock);
+   for (a = app_top; a; a = app_next)
+     {
++      unsigned int status;
++
++      lock_app (a, NULL);
+       app_next = a->next;
+-      if (a->require_get_status)
++
++      if (a->reset_requested)
++        status = 0;
++      else
+         {
+           int sw;
+-          unsigned int status;
+           sw = apdu_get_status (a->slot, 0, &status);
+ 
+           if (sw == SW_HOST_NO_READER)
+@@ -1038,24 +1044,30 @@ scd_update_reader_status_file (void)
+           else if (sw)
+             {
+               /* Get status failed.  Ignore that.  */
++              unlock_app (a);
+               continue;
+             }
++        }
++
++      if (a->card_status != status)
++        {
++          report_change (a->slot, a->card_status, status);
++          send_client_notifications (a, status == 0);
+ 
+-          if (a->card_status != status)
++          if (status == 0)
+             {
+-              report_change (a->slot, a->card_status, status);
+-              send_client_notifications (a, status == 0);
+-
+-              if (status == 0)
+-                {
+-                  log_debug ("Removal of a card: %d\n", a->slot);
+-                  apdu_close_reader (a->slot);
+-                  deallocate_app (a);
+-                }
+-              else
+-                a->card_status = status;
++              log_debug ("Removal of a card: %d\n", a->slot);
++              apdu_close_reader (a->slot);
++              deallocate_app (a);
++            }
++          else
++            {
++              a->card_status = status;
++              unlock_app (a);
+             }
+         }
++      else
++        unlock_app (a);
+     }
+   npth_mutex_unlock (&app_list_lock);
+ }
+diff --git a/scd/command.c b/scd/command.c
+index 0ae6d29..b17c4a1 100644
+--- a/scd/command.c
++++ b/scd/command.c
+@@ -227,7 +227,7 @@ open_card_with_request (ctrl_t ctrl, const char *apptype, const char *serialno)
+ 
+   /* Re-scan USB devices.  Release APP, before the scan.  */
+   ctrl->app_ctx = NULL;
+-  release_application (app);
++  release_application (app, 0);
+ 
+   if (serialno)
+     serialno_bin = hex_to_buffer (serialno, &serialno_bin_len);
+@@ -1492,7 +1492,7 @@ cmd_restart (assuan_context_t ctx, char *line)
+   if (app)
+     {
+       ctrl->app_ctx = NULL;
+-      release_application (app);
++      release_application (app, 0);
+     }
+   if (locked_session && ctrl->server_local == locked_session)
+     {
+@@ -1919,7 +1919,7 @@ send_client_notifications (app_t app, int removal)
+           {
+             sl->ctrl_backlink->app_ctx = NULL;
+             sl->card_removed = 1;
+-            release_application (app);
++            release_application (app, 1);
+           }
+ 
+         if (!sl->event_signal || !sl->assuan_ctx)
+diff --git a/scd/scdaemon.c b/scd/scdaemon.c
+index 74fed44..02f0e72 100644
+--- a/scd/scdaemon.c
++++ b/scd/scdaemon.c
+@@ -52,6 +52,7 @@
+ #include "ccid-driver.h"
+ #include "gc-opt-flags.h"
+ #include "asshelp.h"
++#include "exechelp.h"
+ #include "../common/init.h"
+ 
+ #ifndef ENAMETOOLONG
+@@ -224,7 +225,8 @@ static assuan_sock_nonce_t socket_nonce;
+    disabled but it won't perform any ticker specific actions. */
+ static int ticker_disabled;
+ 
+-
++/* FD to notify update of usb devices.  */
++static int notify_fd;
+ 
+ static char *create_socket_name (char *standard_name);
+ static gnupg_fd_t create_server_socket (const char *name,
+@@ -1181,6 +1183,16 @@ start_connection_thread (void *arg)
+ }
+ 
+ 
++void
++scd_kick_the_loop (void)
++{
++  int ret;
++
++  /* Kick the select loop.  */
++  ret = write (notify_fd, "", 1);
++  (void)ret;
++}
++
+ /* Connection handler loop.  Wait for connection requests and spawn a
+    thread after accepting a connection.  LISTEN_FD is allowed to be -1
+    in which case this code will only do regular timeouts and handle
+@@ -1202,9 +1214,23 @@ handle_connections (int listen_fd)
+ #ifndef HAVE_W32_SYSTEM
+   int signo;
+ #endif
++  int pipe_fd[2];
++
++  ret = gnupg_create_pipe (pipe_fd);
++  if (ret)
++    {
++      log_error ("pipe creation failed: %s\n", gpg_strerror (ret));
++      return;
++    }
++  notify_fd = pipe_fd[1];
+ 
+   ret = npth_attr_init(&tattr);
+-  /* FIXME: Check error.  */
++  if (ret)
++    {
++      log_error ("npth_attr_init failed: %s\n", strerror (ret));
++      return;
++    }
++
+   npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
+ 
+ #ifndef HAVE_W32_SYSTEM
+@@ -1233,6 +1259,8 @@ handle_connections (int listen_fd)
+ 
+   for (;;)
+     {
++      int max_fd;
++
+       if (shutdown_pending)
+         {
+           if (active_connections == 0)
+@@ -1261,14 +1289,20 @@ handle_connections (int listen_fd)
+          thus a simple assignment is fine to copy the entire set.  */
+       read_fdset = fdset;
+ 
++      FD_SET (pipe_fd[0], &read_fdset);
++      if (nfd < pipe_fd[0])
++        max_fd = pipe_fd[0];
++      else
++        max_fd = nfd;
++
+ #ifndef HAVE_W32_SYSTEM
+-      ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, &timeout, npth_sigev_sigmask());
++      ret = npth_pselect (max_fd+1, &read_fdset, NULL, NULL, &timeout, npth_sigev_sigmask());
+       saved_errno = errno;
+ 
+       while (npth_sigev_get_pending(&signo))
+ 	handle_signal (signo);
+ #else
+-      ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, &timeout, NULL, NULL);
++      ret = npth_eselect (max_fd+1, &read_fdset, NULL, NULL, &timeout, NULL, NULL);
+       saved_errno = errno;
+ #endif
+ 
+@@ -1284,6 +1318,13 @@ handle_connections (int listen_fd)
+ 	/* Timeout.  Will be handled when calculating the next timeout.  */
+ 	continue;
+ 
++      if (FD_ISSET (pipe_fd[0], &read_fdset))
++        {
++          char buf[256];
++
++          ret = read (pipe_fd[0], buf, sizeof buf);
++        }
++
+       if (listen_fd != -1 && FD_ISSET (listen_fd, &read_fdset))
+ 	{
+           ctrl_t ctrl;
+@@ -1322,6 +1363,8 @@ handle_connections (int listen_fd)
+ 	}
+     }
+ 
++  close (pipe_fd[0]);
++  close (pipe_fd[1]);
+   cleanup ();
+   log_info (_("%s %s stopped\n"), strusage(11), strusage(13));
+   npth_attr_destroy (&tattr);
+diff --git a/scd/scdaemon.h b/scd/scdaemon.h
+index d0bc98e..fcab648 100644
+--- a/scd/scdaemon.h
++++ b/scd/scdaemon.h
+@@ -125,6 +125,7 @@ void send_status_info (ctrl_t ctrl, const char *keyword, ...)
+ void send_status_direct (ctrl_t ctrl, const char *keyword, const char *args);
+ void scd_update_reader_status_file (void);
+ void send_client_notifications (app_t app, int removal);
++void scd_kick_the_loop (void);
+ 
+ 
+ #endif /*SCDAEMON_H*/
diff -Nru gnupg2-2.1.18/debian/patches/0031-gpg-Fix-aliases-list-key-list-sig-and-check-sig.patch gnupg2-2.1.18/debian/patches/0031-gpg-Fix-aliases-list-key-list-sig-and-check-sig.patch
--- gnupg2-2.1.18/debian/patches/0031-gpg-Fix-aliases-list-key-list-sig-and-check-sig.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0031-gpg-Fix-aliases-list-key-list-sig-and-check-sig.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,66 @@
+From: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
+Date: Sat, 4 Feb 2017 01:23:32 -0500
+Subject: gpg: Fix aliases --list-key, --list-sig, and --check-sig.
+
+* g10/gpg.c (opts): Define commands with ARGPARSE_c
+instead of ARGPARSE_s_n.
+
+--
+
+These three entries are commands, but they're being treated as a
+string-based option for some reason.  However, if you try to use them
+concurrently with another command like --clearsign, you'll get "gpg:
+conflicting commands".
+
+Furthermore, because they're marked as options, their flags differ
+from the commands that they alias, they cause ambiguity in
+abbreviation (e.g. try "gpg --list-ke") which should have been fixed
+by 7249ab0f95d1f6cb8ee61eefedc79801bb56398f.
+
+Marking them explicitly as commands for argparse should be more
+accurate and should resolve the abbreviation ambiguity issue.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
+gpg: fix aliases --list-key, --list-sig, and --check-sig.
+
+* g10/gpg.c: ARGPARSE_OPTS opts[]: define commands with ARGPARSE_c
+instead of ARGPARSE_s_n.
+
+--
+
+These three entries are commands, but they're being treated as a
+string-based option for some reason.  However, if you try to use them
+concurrently with another command like --clearsign, you'll get "gpg:
+conflicting commands".
+
+Furthermore, because they're marked as options, their flags differ
+from the commands that they alias, they cause ambiguity in
+abbreviation (e.g. try "gpg --list-ke") which should have been fixed
+by 7249ab0f95d1f6cb8ee61eefedc79801bb56398f.
+
+Marking them explicitly as commands for argparse should be more
+accurate and should resolve the abbreviation ambiguity issue.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
+(cherry picked from commit f31120a5aa40b6e4e89d41d1d5d34e0f7da173b4)
+---
+ g10/gpg.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/g10/gpg.c b/g10/gpg.c
+index f9039ae..e280c22 100644
+--- a/g10/gpg.c
++++ b/g10/gpg.c
+@@ -728,9 +728,9 @@ static ARGPARSE_OPTS opts[] = {
+   ARGPARSE_s_n (oWithKeyData,"with-key-data", "@"),
+   ARGPARSE_s_n (oWithSigList,"with-sig-list", "@"),
+   ARGPARSE_s_n (oWithSigCheck,"with-sig-check", "@"),
+-  ARGPARSE_s_n (aListKeys, "list-key", "@"),   /* alias */
+-  ARGPARSE_s_n (aListSigs, "list-sig", "@"),   /* alias */
+-  ARGPARSE_s_n (aCheckKeys, "check-sig", "@"), /* alias */
++  ARGPARSE_c (aListKeys, "list-key", "@"),   /* alias */
++  ARGPARSE_c (aListSigs, "list-sig", "@"),   /* alias */
++  ARGPARSE_c (aCheckKeys, "check-sig", "@"), /* alias */
+   ARGPARSE_s_n (oSkipVerify, "skip-verify", "@"),
+   ARGPARSE_s_n (oSkipHiddenRecipients, "skip-hidden-recipients", "@"),
+   ARGPARSE_s_n (oNoSkipHiddenRecipients, "no-skip-hidden-recipients", "@"),
diff -Nru gnupg2-2.1.18/debian/patches/0032-gpg-common-Make-sure-that-all-fd-given-are-valid.patch gnupg2-2.1.18/debian/patches/0032-gpg-common-Make-sure-that-all-fd-given-are-valid.patch
--- gnupg2-2.1.18/debian/patches/0032-gpg-common-Make-sure-that-all-fd-given-are-valid.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0032-gpg-common-Make-sure-that-all-fd-given-are-valid.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,228 @@
+From: Justus Winter <justus at g10code.com>
+Date: Wed, 8 Feb 2017 13:49:41 +0100
+Subject: gpg,common: Make sure that all fd given are valid.
+
+* common/sysutils.c (gnupg_fd_valid): New function.
+* common/sysutils.h (gnupg_fd_valid): New declaration.
+* common/logging.c (log_set_file): Use the new function.
+* g10/cpr.c (set_status_fd): Likewise.
+* g10/gpg.c (main): Likewise.
+* g10/keylist.c (read_sessionkey_from_fd): Likewise.
+* g10/passphrase.c (set_attrib_fd): Likewise.
+* tests/openpgp/Makefile.am (XTESTS): Add the new test.
+* tests/openpgp/issue2941.scm: New file.
+--
+
+Consider a situation where the user passes "--status-fd 3" but file
+descriptor 3 is not open.
+
+During the course of executing the rest of the commands, it's possible
+that gpg itself will open some files, and file descriptor 3 will get
+allocated.
+
+In this situation, the status information will be appended directly to
+whatever file happens to have landed on fd 3 (the trustdb? the
+keyring?).
+
+This is a potential data destruction issue for all writable file
+descriptor options:
+
+   --status-fd
+   --attribute-fd
+   --logger-fd
+
+It's also a potential issue for readable file descriptor options, but
+the risk is merely weird behavior, and not data corruption:
+
+   --override-session-key-fd
+   --passphrase-fd
+   --command-fd
+
+Fixes this by checking whether the fd is valid early on before using
+it.
+
+GnuPG-bug-id: 2941
+Signed-off-by: Justus Winter <justus at g10code.com>
+(cherry picked from commit 6823ed46584e753de3aba48a00ab738ab009a860)
+---
+ common/logging.c            |  3 +++
+ common/sysutils.c           | 11 +++++++++++
+ common/sysutils.h           |  1 +
+ g10/cpr.c                   |  3 +++
+ g10/gpg.c                   |  5 +++++
+ g10/keylist.c               |  3 +++
+ g10/passphrase.c            |  3 +++
+ tests/openpgp/Makefile.am   |  4 ++--
+ tests/openpgp/issue2941.scm | 34 ++++++++++++++++++++++++++++++++++
+ 9 files changed, 65 insertions(+), 2 deletions(-)
+ create mode 100755 tests/openpgp/issue2941.scm
+
+diff --git a/common/logging.c b/common/logging.c
+index 8c70742..ac13053 100644
+--- a/common/logging.c
++++ b/common/logging.c
+@@ -570,6 +570,9 @@ log_set_file (const char *name)
+ void
+ log_set_fd (int fd)
+ {
++  if (! gnupg_fd_valid (fd))
++    log_fatal ("logger-fd is invalid: %s\n", strerror (errno));
++
+   set_file_fd (NULL, fd);
+ }
+ 
+diff --git a/common/sysutils.c b/common/sysutils.c
+index e67420f..a796677 100644
+--- a/common/sysutils.c
++++ b/common/sysutils.c
+@@ -1281,3 +1281,14 @@ gnupg_get_socket_name (int fd)
+   return name;
+ }
+ #endif /*!HAVE_W32_SYSTEM*/
++
++/* Check whether FD is valid.  */
++int
++gnupg_fd_valid (int fd)
++{
++  int d = dup (fd);
++  if (d < 0)
++    return 0;
++  close (d);
++  return 1;
++}
+diff --git a/common/sysutils.h b/common/sysutils.h
+index a9316d7..ecd9f84 100644
+--- a/common/sysutils.h
++++ b/common/sysutils.h
+@@ -72,6 +72,7 @@ int  gnupg_setenv (const char *name, const char *value, int overwrite);
+ int  gnupg_unsetenv (const char *name);
+ char *gnupg_getcwd (void);
+ char *gnupg_get_socket_name (int fd);
++int gnupg_fd_valid (int fd);
+ 
+ gpg_error_t gnupg_inotify_watch_socket (int *r_fd, const char *socket_name);
+ int gnupg_inotify_has_name (int fd, const char *name);
+diff --git a/g10/cpr.c b/g10/cpr.c
+index 0133cad..4984e89 100644
+--- a/g10/cpr.c
++++ b/g10/cpr.c
+@@ -107,6 +107,9 @@ set_status_fd (int fd)
+   if (fd == -1)
+     return;
+ 
++  if (! gnupg_fd_valid (fd))
++    log_fatal ("status-fd is invalid: %s\n", strerror (errno));
++
+   if (fd == 1)
+     statusfp = es_stdout;
+   else if (fd == 2)
+diff --git a/g10/gpg.c b/g10/gpg.c
+index e280c22..66a2055 100644
+--- a/g10/gpg.c
++++ b/g10/gpg.c
+@@ -3079,6 +3079,8 @@ main (int argc, char **argv)
+ 
+ 	  case oCommandFD:
+             opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
++	    if (! gnupg_fd_valid (opt.command_fd))
++	      log_fatal ("command-fd is invalid: %s\n", strerror (errno));
+             break;
+ 	  case oCommandFile:
+             opt.command_fd = open_info_file (pargs.r.ret_str, 0, 1);
+@@ -5293,6 +5295,9 @@ read_sessionkey_from_fd (int fd)
+   int i, len;
+   char *line;
+ 
++  if (! gnupg_fd_valid (fd))
++    log_fatal ("override-session-key-fd is invalid: %s\n", strerror (errno));
++
+   for (line = NULL, i = len = 100; ; i++ )
+     {
+       if (i >= len-1 )
+diff --git a/g10/keylist.c b/g10/keylist.c
+index 4fe1e40..abdcb9f 100644
+--- a/g10/keylist.c
++++ b/g10/keylist.c
+@@ -1900,6 +1900,9 @@ set_attrib_fd (int fd)
+   if (fd == -1)
+     return;
+ 
++  if (! gnupg_fd_valid (fd))
++    log_fatal ("attribute-fd is invalid: %s\n", strerror (errno));
++
+ #ifdef HAVE_DOSISH_SYSTEM
+   setmode (fd, O_BINARY);
+ #endif
+diff --git a/g10/passphrase.c b/g10/passphrase.c
+index fb4ec4c..37abc0f 100644
+--- a/g10/passphrase.c
++++ b/g10/passphrase.c
+@@ -166,6 +166,9 @@ read_passphrase_from_fd( int fd )
+   int i, len;
+   char *pw;
+ 
++  if (! gnupg_fd_valid (fd))
++    log_fatal ("passphrase-fd is invalid: %s\n", strerror (errno));
++
+   if ( !opt.batch && opt.pinentry_mode != PINENTRY_MODE_LOOPBACK)
+     { /* Not used but we have to do a dummy read, so that it won't end
+          up at the begin of the message if the quite usual trick to
+diff --git a/tests/openpgp/Makefile.am b/tests/openpgp/Makefile.am
+index 05341fb..377a2ed 100644
+--- a/tests/openpgp/Makefile.am
++++ b/tests/openpgp/Makefile.am
+@@ -95,12 +95,12 @@ XTESTS = \
+ 	issue2015.scm \
+ 	issue2346.scm \
+ 	issue2417.scm \
+-	issue2419.scm
++	issue2419.scm \
++	issue2941.scm
+ 
+ # Fixme: gpgconf.scm does not yet work with make distcheck.
+ #	gpgconf.scm
+ 
+-
+ # XXX: Currently, one cannot override automake's 'check' target.  As a
+ # workaround, we avoid defining 'TESTS', thus automake will not emit
+ # the 'check' target.  For extra robustness, we merely define a
+diff --git a/tests/openpgp/issue2941.scm b/tests/openpgp/issue2941.scm
+new file mode 100755
+index 0000000..d7220e0
+--- /dev/null
++++ b/tests/openpgp/issue2941.scm
+@@ -0,0 +1,34 @@
++#!/usr/bin/env gpgscm
++
++;; Copyright (C) 2017 g10 Code GmbH
++;;
++;; This file is part of GnuPG.
++;;
++;; GnuPG is free software; you can redistribute it and/or modify
++;; it under the terms of the GNU General Public License as published by
++;; the Free Software Foundation; either version 3 of the License, or
++;; (at your option) any later version.
++;;
++;; GnuPG is distributed in the hope that it will be useful,
++;; but WITHOUT ANY WARRANTY; without even the implied warranty of
++;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++;; GNU General Public License for more details.
++;;
++;; You should have received a copy of the GNU General Public License
++;; along with this program; if not, see <http://www.gnu.org/licenses/>.
++
++(load (with-path "defs.scm"))
++(setup-legacy-environment)
++
++(define (check-failure options)
++  (let ((command `(, at gpg , at options)))
++    (catch '()
++	   (call-check command)
++	   (error "Expected an error, but got none when executing" command))))
++
++(for-each-p
++ "Checking invocation with invalid file descriptors (issue2941)."
++ (lambda (option)
++   (check-failure `(,(string-append "--" option "=23") --sign gpg.conf)))
++ '("status-fd" "attribute-fd" "logger-fd"
++   "override-session-key-fd" "passphrase-fd" "command-fd"))
diff -Nru gnupg2-2.1.18/debian/patches/0033-common-Avoid-warning-about-implicit-declaration-of-g.patch gnupg2-2.1.18/debian/patches/0033-common-Avoid-warning-about-implicit-declaration-of-g.patch
--- gnupg2-2.1.18/debian/patches/0033-common-Avoid-warning-about-implicit-declaration-of-g.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0033-common-Avoid-warning-about-implicit-declaration-of-g.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,36 @@
+From: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
+Date: Wed, 8 Feb 2017 12:05:08 -0500
+Subject: common: Avoid warning about implicit declaration of gnupg_fd_valid.
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+* common/logging.c: Add #include "sysutils.h".
+
+--
+
+Without this, we see:
+
+logging.c:573:9: warning: implicit declaration of function \
+  ?gnupg_fd_valid? [-Wimplicit-function-declaration]
+   if (! gnupg_fd_valid (fd))
+         ^~~~~~~~~~~~~~
+
+Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
+(cherry picked from commit 8810314e377a9cb6612150a57cf99260ed0bb9f6)
+---
+ common/logging.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/common/logging.c b/common/logging.c
+index ac13053..670affb 100644
+--- a/common/logging.c
++++ b/common/logging.c
+@@ -61,6 +61,7 @@
+ #include "i18n.h"
+ #include "common-defs.h"
+ #include "logging.h"
++#include "sysutils.h"
+ 
+ #ifdef HAVE_W32_SYSTEM
+ # define S_IRGRP S_IRUSR
diff -Nru gnupg2-2.1.18/debian/patches/0034-gpg-Fix-memory-leak-in-the-error-case-of-signature-c.patch gnupg2-2.1.18/debian/patches/0034-gpg-Fix-memory-leak-in-the-error-case-of-signature-c.patch
--- gnupg2-2.1.18/debian/patches/0034-gpg-Fix-memory-leak-in-the-error-case-of-signature-c.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0034-gpg-Fix-memory-leak-in-the-error-case-of-signature-c.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,51 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Fri, 10 Feb 2017 17:16:07 +0100
+Subject: gpg: Fix memory leak in the error case of signature creation.
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+* g10/sign.c (write_signature_packets): Free SIG.  Also replace
+xcalloc by xtrycalloc.
+--
+
+If do_sign fails SIG was not released.  Note that in the good case SIG
+is transferred to PKT and freed by free_packet.
+
+Reported-by: Stephan M?ller
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 5996c7bf99f3a681393fd9589276399ebc956cff)
+---
+ g10/sign.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/g10/sign.c b/g10/sign.c
+index acc894c..ff099b3 100644
+--- a/g10/sign.c
++++ b/g10/sign.c
+@@ -686,7 +686,10 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
+       pk = sk_rover->pk;
+ 
+       /* Build the signature packet.  */
+-      sig = xmalloc_clear (sizeof *sig);
++      sig = xtrycalloc (1, sizeof *sig);
++      if (!sig)
++        return gpg_error_from_syserror ();
++
+       if (duration || opt.sig_policy_url
+           || opt.sig_notations || opt.sig_keyserver_url)
+         sig->version = 4;
+@@ -731,8 +734,12 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
+             print_status_sig_created (pk, sig, status_letter);
+           free_packet (&pkt);
+           if (rc)
+-            log_error ("build signature packet failed: %s\n", gpg_strerror (rc));
++            log_error ("build signature packet failed: %s\n",
++                       gpg_strerror (rc));
+ 	}
++      else
++        xfree (sig);
++
+       if (rc)
+         return rc;
+     }
diff -Nru gnupg2-2.1.18/debian/patches/0035-gpg-Print-a-warning-if-no-command-has-been-given.patch gnupg2-2.1.18/debian/patches/0035-gpg-Print-a-warning-if-no-command-has-been-given.patch
--- gnupg2-2.1.18/debian/patches/0035-gpg-Print-a-warning-if-no-command-has-been-given.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0035-gpg-Print-a-warning-if-no-command-has-been-given.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,32 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Mon, 13 Feb 2017 13:09:51 +0100
+Subject: gpg: Print a warning if no command has been given.
+
+* g10/gpg.c (main): Print in the default case.
+--
+
+GnuPG-bug-id: 2943
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 810adfd47801fc01e45fb71af9f05c91f7890cdb)
+---
+ g10/gpg.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/g10/gpg.c b/g10/gpg.c
+index 66a2055..0c5a167 100644
+--- a/g10/gpg.c
++++ b/g10/gpg.c
+@@ -4894,8 +4894,12 @@ main (int argc, char **argv)
+ #endif /*USE_TOFU*/
+ 	break;
+ 
+-      case aListPackets:
+       default:
++        if (!opt.quiet)
++          log_info (_("WARNING: no command supplied."
++                      "  Trying to guess what you mean ...\n"));
++        /*FALLTHU*/
++      case aListPackets:
+ 	if( argc > 1 )
+ 	    wrong_args("[filename]");
+ 	/* Issue some output for the unix newbie */
diff -Nru gnupg2-2.1.18/debian/patches/0036-gpgconf-No-ENOENT-warning-with-change-options-et-al.patch gnupg2-2.1.18/debian/patches/0036-gpgconf-No-ENOENT-warning-with-change-options-et-al.patch
--- gnupg2-2.1.18/debian/patches/0036-gpgconf-No-ENOENT-warning-with-change-options-et-al.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0036-gpgconf-No-ENOENT-warning-with-change-options-et-al.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,40 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Mon, 13 Feb 2017 19:38:53 +0100
+Subject: gpgconf: No ENOENT warning with --change-options et al.
+
+* tools/gpgconf-comp.c (retrieve_options_from_program): Check ERRNO
+before printing a warning.
+--
+
+It is common that a conf files does not exist - thus we should not
+print a warning.
+
+GnuPG-bug-id: 2944
+
+BTW: The error messages in gpgconf should be reworked to match those
+of the other components.
+
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 30dac0486b6357e84fbe79c612eea940b654e4d1)
+---
+ tools/gpgconf-comp.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
+index 180fd65..a0d9659 100644
+--- a/tools/gpgconf-comp.c
++++ b/tools/gpgconf-comp.c
+@@ -2163,8 +2163,11 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
+ 
+   config = es_fopen (config_filename, "r");
+   if (!config)
+-    gc_error (0, errno, "warning: can not open config file %s",
+-	      config_filename);
++    {
++      if (errno != ENOENT)
++        gc_error (0, errno, "warning: can not open config file %s",
++                  config_filename);
++    }
+   else
+     {
+       while ((length = es_read_line (config, &line, &line_len, NULL)) > 0)
diff -Nru gnupg2-2.1.18/debian/patches/0037-dirmngr-Do-a-DNS-lookup-even-if-it-is-missing-from-n.patch gnupg2-2.1.18/debian/patches/0037-dirmngr-Do-a-DNS-lookup-even-if-it-is-missing-from-n.patch
--- gnupg2-2.1.18/debian/patches/0037-dirmngr-Do-a-DNS-lookup-even-if-it-is-missing-from-n.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0037-dirmngr-Do-a-DNS-lookup-even-if-it-is-missing-from-n.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,60 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Mon, 13 Feb 2017 20:09:26 +0100
+Subject: dirmngr: Do a DNS lookup even if it is missing from nsswitch.conf.
+
+* dirmngr/dns-stuff.c (libdns_init): Do not print error message for a
+missing nsswitch.conf.  Make sure that tehre is a DNS entry.
+--
+
+GnuPG-bug-id: 2948
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit dee026d761ae3d7594c3dbc5b3fa842df53cc189)
+---
+ dirmngr/dns-stuff.c | 27 +++++++++++++++++++++------
+ 1 file changed, 21 insertions(+), 6 deletions(-)
+
+diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c
+index 52f011a..bc2e071 100644
+--- a/dirmngr/dns-stuff.c
++++ b/dirmngr/dns-stuff.c
+@@ -498,12 +498,10 @@ libdns_init (void)
+         (dns_nssconf_loadpath (ld.resolv_conf, fname));
+       if (err)
+         {
+-          log_error ("failed to load '%s': %s\n", fname, gpg_strerror (err));
+-          /* not fatal, nsswitch.conf is not used on all systems; assume
+-           * classic behavior instead.  Our dns library states "bf" which tries
+-           * DNS then Files, which is not classic; FreeBSD
+-           * /usr/src/lib/libc/net/gethostnamadr.c defines default_src[] which
+-           * is Files then DNS, which is. */
++          /* This is not a fatal error: nsswitch.conf is not used on
++           * all systems; assume classic behavior instead.  */
++          if (gpg_err_code (err) != GPG_ERR_ENOENT)
++            log_error ("failed to load '%s': %s\n", fname, gpg_strerror (err));
+           if (opt_debug)
+             log_debug ("dns: fallback resolution order, files then DNS\n");
+           ld.resolv_conf->lookup[0] = 'f';
+@@ -511,6 +509,23 @@ libdns_init (void)
+           ld.resolv_conf->lookup[2] = '\0';
+           err = GPG_ERR_NO_ERROR;
+         }
++      else if (!strchr (ld.resolv_conf->lookup, 'b'))
++        {
++          /* No DNS resulution type found in the list.  This might be
++           * due to systemd based systems which allow for custom
++           * keywords which are not known to us and thus we do not
++           * know whether DNS is wanted or not.  Becuase DNS is
++           * important for our infrastructure, we forcefully append
++           * DNS to the end of the list.  */
++          if (strlen (ld.resolv_conf->lookup)+2 < sizeof ld.resolv_conf->lookup)
++            {
++              if (opt_debug)
++                log_debug ("dns: appending DNS to resolution order\n");
++              strcat (ld.resolv_conf->lookup, "b");
++            }
++          else
++            log_error ("failed to append DNS to resolution order\n");
++        }
+ 
+ #endif /* Unix */
+     }
diff -Nru gnupg2-2.1.18/debian/patches/0038-gpg-Make-export-ssh-key-work-for-the-primary-key.patch gnupg2-2.1.18/debian/patches/0038-gpg-Make-export-ssh-key-work-for-the-primary-key.patch
--- gnupg2-2.1.18/debian/patches/0038-gpg-Make-export-ssh-key-work-for-the-primary-key.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0038-gpg-Make-export-ssh-key-work-for-the-primary-key.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,162 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Tue, 14 Feb 2017 10:55:13 +0100
+Subject: gpg: Make --export-ssh-key work for the primary key.
+
+* g10/export.c (export_ssh_key): Also check the primary key.
+--
+
+If no suitable subkey was found for export, we now check whether the
+primary key is suitable for export and export this one.  Without this
+change it was only possible to export the primary key by using the '!'
+suffix in the key specification.
+
+Also added a sample key for testing this.
+
+GnuPG-bug-id: 2957
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit b456e5be91dc064fc9509ea86edab113721ed299)
+---
+ g10/export.c                                       | 42 ++++++++++++++++++++++
+ tests/openpgp/samplekeys/README                    |  2 ++
+ .../samplekeys/rsa-primary-auth-only.pub.asc       | 23 ++++++++++++
+ .../samplekeys/rsa-primary-auth-only.sec.asc       | 38 ++++++++++++++++++++
+ 4 files changed, 105 insertions(+)
+ create mode 100644 tests/openpgp/samplekeys/rsa-primary-auth-only.pub.asc
+ create mode 100644 tests/openpgp/samplekeys/rsa-primary-auth-only.sec.asc
+
+diff --git a/g10/export.c b/g10/export.c
+index f354ca0..8668126 100644
+--- a/g10/export.c
++++ b/g10/export.c
+@@ -2208,6 +2208,48 @@ export_ssh_key (ctrl_t ctrl, const char *userid)
+               latest_key = node;
+             }
+         }
++
++      /* If no subkey was suitable check the primary key.  */
++      if (!latest_key
++          && (node = keyblock) && node->pkt->pkttype == PKT_PUBLIC_KEY)
++        {
++          pk = node->pkt->pkt.public_key;
++          if (DBG_LOOKUP)
++            log_debug ("\tchecking primary key %08lX\n",
++                       (ulong) keyid_from_pk (pk, NULL));
++          if (!(pk->pubkey_usage & PUBKEY_USAGE_AUTH))
++            {
++              if (DBG_LOOKUP)
++                log_debug ("\tprimary key not usable for authentication\n");
++            }
++          else if (!pk->flags.valid)
++            {
++              if (DBG_LOOKUP)
++                log_debug ("\tprimary key not valid\n");
++            }
++          else if (pk->flags.revoked)
++            {
++              if (DBG_LOOKUP)
++                log_debug ("\tprimary key has been revoked\n");
++            }
++          else if (pk->has_expired)
++            {
++              if (DBG_LOOKUP)
++                log_debug ("\tprimary key has expired\n");
++            }
++          else if (pk->timestamp > curtime && !opt.ignore_valid_from)
++            {
++              if (DBG_LOOKUP)
++                log_debug ("\tprimary key not yet valid\n");
++            }
++          else
++            {
++              if (DBG_LOOKUP)
++                log_debug ("\tprimary key is fine\n");
++              latest_date = pk->timestamp;
++              latest_key = node;
++            }
++        }
+     }
+ 
+   if (!latest_key)
+diff --git a/tests/openpgp/samplekeys/README b/tests/openpgp/samplekeys/README
+index 29524d5..6f2399f 100644
+--- a/tests/openpgp/samplekeys/README
++++ b/tests/openpgp/samplekeys/README
+@@ -17,3 +17,5 @@ E657FB607BB4F21C90BB6651BC067AF28BC90111.asc Key with subkeys (no protection)
+ rsa-rsa-sample-1.asc   RSA+RSA sample key (no passphrase)
+ ed25519-cv25519-sample-1.asc  Ed25519+CV25519 sample key (no passphrase)
+ silent-running.asc     Collection of sample secret keys (no passphrases)
++rsa-primary-auth-only.pub.asc  rsa2408 primary only, usage: cert,auth
++rsa-primary-auth-only.sec.asc  Ditto but the secret keyblock.
+diff --git a/tests/openpgp/samplekeys/rsa-primary-auth-only.pub.asc b/tests/openpgp/samplekeys/rsa-primary-auth-only.pub.asc
+new file mode 100644
+index 0000000..f34999e
+--- /dev/null
++++ b/tests/openpgp/samplekeys/rsa-primary-auth-only.pub.asc
+@@ -0,0 +1,23 @@
++pub   rsa2048 2017-02-14 [CA]
++      F74B4029E6906D12EBDA8EE3BD7744900FDABC8D
++      Keygrip = AB1BB1843677AF7CC4D6C14444320C3FF4147E98
++uid           [ unknown] ssh://host.example.net
++
++-----BEGIN PGP PUBLIC KEY BLOCK-----
++
++mQENBFiizWgBCACi28riS0AaC7UvXaZfoafEvcXq/MAq6akiowPf3eY4zz5DkBPf
++Ep3kGuDMAFqULvchIt9vpg719Zar/Xldi+UG+/KsDz+TT5k+nP6CwvBHbAXXtISv
++S51TKKnTFpvjcgJc1BMFN0pGf7JnZx1QfRfsZO2BvS4qVzYCWbSS9hlpMq4aIgOc
++ERBMsZYMPnI4ijbXysksecDC91kbJH0q5j8aGir5sDyrDwfVLp0SUAubRFU5gXuZ
++SEv9QmeV7XoXKXzk9KEYy7GUgoAJzabvbF0rVXqd3DE8KFkwK7rKBe8sGC04DWlK
++j/sHJcAfMSqCi/SZyYpO+FSfnB+uJ1BNc05hABEBAAG0FnNzaDovL2hvc3QuZXhh
++bXBsZS5uZXSJAU4EEwEIADgWIQT3S0Ap5pBtEuvajuO9d0SQD9q8jQUCWKLNaAIb
++IQULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRC9d0SQD9q8jZBrB/41MJWUeclV
++tM60+ydPNgUJwyRXpKdLIm/AtM1zOijlFkwsaMmzbFSFJJX98HGASHdU5OpL2Lv3
++1NNDNMbUuFumApVrLzJUBugFRb+8/uY7H3Z0/YKQ9g9OC3z7+uqFFv/+/wA+VdYX
++Zy6uim8E4OlJ41S68fQcMiTxbLTCDkvBbpf505t6JhNqF6JB+SBFQJXvRqjoydXf
++dyoiDz9N1V0ERzmGEiPewvHg2zWcVia07NGhxN3slQ3klOfYJQ8Ye72feNq1zKCy
++AyU3X8fL10XKWooCAU+t4hR5hXYxYTSZse5q0FHZ38Lt9c3ApMSZ2+ueeOtGbsH9
++kV8icGkI6KXp
++=zMXp
++-----END PGP PUBLIC KEY BLOCK-----
+diff --git a/tests/openpgp/samplekeys/rsa-primary-auth-only.sec.asc b/tests/openpgp/samplekeys/rsa-primary-auth-only.sec.asc
+new file mode 100644
+index 0000000..9d72421
+--- /dev/null
++++ b/tests/openpgp/samplekeys/rsa-primary-auth-only.sec.asc
+@@ -0,0 +1,38 @@
++sec   rsa2048 2017-02-14 [CA]
++      F74B4029E6906D12EBDA8EE3BD7744900FDABC8D
++      Keygrip = AB1BB1843677AF7CC4D6C14444320C3FF4147E98
++uid           [ unknown] ssh://host.example.net
++
++Passprase: none
++
++-----BEGIN PGP PRIVATE KEY BLOCK-----
++
++lQOYBFiizWgBCACi28riS0AaC7UvXaZfoafEvcXq/MAq6akiowPf3eY4zz5DkBPf
++Ep3kGuDMAFqULvchIt9vpg719Zar/Xldi+UG+/KsDz+TT5k+nP6CwvBHbAXXtISv
++S51TKKnTFpvjcgJc1BMFN0pGf7JnZx1QfRfsZO2BvS4qVzYCWbSS9hlpMq4aIgOc
++ERBMsZYMPnI4ijbXysksecDC91kbJH0q5j8aGir5sDyrDwfVLp0SUAubRFU5gXuZ
++SEv9QmeV7XoXKXzk9KEYy7GUgoAJzabvbF0rVXqd3DE8KFkwK7rKBe8sGC04DWlK
++j/sHJcAfMSqCi/SZyYpO+FSfnB+uJ1BNc05hABEBAAEAB/wN0yan4HIdQ+fU5i2c
++v0uknI9+i9zW8mWUi84Puks0K15CZ1VTLHC8JQ6hgq4twhw3HeS7GkJO3X2K4BuQ
++tggdIv94slqtQKaQ9XbNgYraz/AMXZtIiNy0FdGaGmM6rY+ccwxM9w1BFXn+48v4
++lzCUCq/2wX53wwDSC5dpRPw8km6+uksFh3dfY8kgfpjU/lUCCwQiooYrQhut1EGB
++lDLRHp2ntC1xsnowtdPzluIHFetFSnmn2ehGqXqXtXLAMF0HOirViO5dUVMuj2Pe
++ra3IYVYANYK/7FEsRXHxU6aB/BSnubb5EiqB1Oi1JNyMrvYZnRsoRUaMjVgjA4ne
++RwD5BADBZN2USYGgciDVh7kvTbrtS1igPhoe3xUUQsM0hVIEwBzG4A4pWXznIQyW
++BziVTnRNp953EbHJIYdn7vmJzdiRKI+hOvrF8dfvVsq+fp4pWxrc+zrC6qptpo6H
++IhkHWUpyfIPuTI8d+glIUIuDshwKau0UZ8VDTOYuRYEZX9PrAwQA15RdS3geA1cf
++UK/ZaKs5VnohcLtEE/z3BlvlQaEdHxSQJSLYC4By7zKVOFZlZkHk36IPikwYNTgc
++P57aLe7rwNZqPhADue1ZN6Ypetvrek55lAYL9XoPJ/mWaYz6oDWWW8vHYqEPk8OL
++N8/8a6DhK0iydXi9/ztHQllbOt0EUcsEAJBjX84FgIi3VRotRSEDN/tIhekNo8p6
++Pl8YF4V8A1hCVBEKRIcsPVx603DFiGFRcQQcBbblqVG4fpOYYgiBtEgJksRiMg/o
++kmVkl8BPrIhBGe2ez7byhhFvJDAoOWCdH0MWGaPGUoCGTDvd046GE8B3UWN9TSmo
++qAqfrUG0hQVQLEa0FnNzaDovL2hvc3QuZXhhbXBsZS5uZXSJAU4EEwEIADgWIQT3
++S0Ap5pBtEuvajuO9d0SQD9q8jQUCWKLNaAIbIQULCQgHAgYVCAkKCwIEFgIDAQIe
++AQIXgAAKCRC9d0SQD9q8jZBrB/41MJWUeclVtM60+ydPNgUJwyRXpKdLIm/AtM1z
++OijlFkwsaMmzbFSFJJX98HGASHdU5OpL2Lv31NNDNMbUuFumApVrLzJUBugFRb+8
++/uY7H3Z0/YKQ9g9OC3z7+uqFFv/+/wA+VdYXZy6uim8E4OlJ41S68fQcMiTxbLTC
++DkvBbpf505t6JhNqF6JB+SBFQJXvRqjoydXfdyoiDz9N1V0ERzmGEiPewvHg2zWc
++Via07NGhxN3slQ3klOfYJQ8Ye72feNq1zKCyAyU3X8fL10XKWooCAU+t4hR5hXYx
++YTSZse5q0FHZ38Lt9c3ApMSZ2+ueeOtGbsH9kV8icGkI6KXp
++=3QG9
++-----END PGP PRIVATE KEY BLOCK-----
diff -Nru gnupg2-2.1.18/debian/patches/0039-dirmngr-Avoid-PTR-lookup-for-hosts-in-a-pool.patch gnupg2-2.1.18/debian/patches/0039-dirmngr-Avoid-PTR-lookup-for-hosts-in-a-pool.patch
--- gnupg2-2.1.18/debian/patches/0039-dirmngr-Avoid-PTR-lookup-for-hosts-in-a-pool.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0039-dirmngr-Avoid-PTR-lookup-for-hosts-in-a-pool.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,71 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Wed, 15 Feb 2017 17:03:57 +0100
+Subject: dirmngr: Avoid PTR lookup for hosts in a pool
+
+* dirmngr/ks-engine-hkp.c (add_host): Don't to a PTR lookup for hosts
+in a pool.
+--
+
+GnuPG-bug-id: 2928
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit da2ba20868093e3054d18adc2b1bc56cb23e4ba7)
+---
+ dirmngr/ks-engine-hkp.c | 23 ++++++++++++++++++-----
+ 1 file changed, 18 insertions(+), 5 deletions(-)
+
+diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
+index be8b083..32db4bc 100644
+--- a/dirmngr/ks-engine-hkp.c
++++ b/dirmngr/ks-engine-hkp.c
+@@ -320,10 +320,17 @@ add_host (const char *name, int is_pool,
+ 
+   idx = find_hostinfo (name);
+ 
+-  if (!is_pool && !is_ip_address (name))
++  if (is_pool)
+     {
+-      /* This is a hostname but not a pool.  Use the name
+-         as given without going through resolve_dns_addr.  */
++      /* For a pool immediately convert the address to a string.  */
++      tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
++                                 (DNS_NUMERICHOST | DNS_WITHBRACKET), &tmphost);
++      is_numeric = 1;
++    }
++  else if (!is_ip_address (name))
++    {
++      /* This is a hostname.  Use the name as given without going
++       * through resolve_dns_addr.  */
+       tmphost = xtrystrdup (name);
+       if (!tmphost)
+         tmperr = gpg_error_from_syserror ();
+@@ -332,6 +339,10 @@ add_host (const char *name, int is_pool,
+     }
+   else
+     {
++      /* Do a PTR lookup on AI.  If a name was not found the function
++       * returns the numeric address (with brackets) and we set a flag
++       * so that we know that the conversion to a numerical string has
++       * already be done.  */
+       tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
+                                  DNS_WITHBRACKET, &tmphost);
+       if (tmphost && is_ip_address (tmphost))
+@@ -364,8 +375,7 @@ add_host (const char *name, int is_pool,
+ 
+       if (tmpidx == -1)
+         {
+-          log_error ("map_host for '%s' problem: %s - '%s'"
+-                     " [ignored]\n",
++          log_error ("map_host for '%s' problem: %s - '%s' [ignored]\n",
+                      name, strerror (errno), tmphost);
+         }
+       else  /* Set or update the entry. */
+@@ -375,6 +385,9 @@ add_host (const char *name, int is_pool,
+           if (port)
+             hosttable[tmpidx]->port = port;
+ 
++          /* If TMPHOST is not yet a numerical value do this now.
++           * Note: This is a simple string operations and not a PTR
++           * lookup (due to DNS_NUMERICHOST).  */
+           if (!is_numeric)
+             {
+               xfree (tmphost);
diff -Nru gnupg2-2.1.18/debian/patches/0040-gpgv-w32-Fix-status-fd.patch gnupg2-2.1.18/debian/patches/0040-gpgv-w32-Fix-status-fd.patch
--- gnupg2-2.1.18/debian/patches/0040-gpgv-w32-Fix-status-fd.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0040-gpgv-w32-Fix-status-fd.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,27 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Tue, 28 Feb 2017 09:35:41 +0100
+Subject: gpgv,w32: Fix --status-fd.
+
+* g10/gpgv.c (main): Use translate_sys2libc_fd_int for --status-fd.
+
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 8a67dc4c4324b617b5a3fea51c59c674488544d6)
+---
+ g10/gpgv.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/g10/gpgv.c b/g10/gpgv.c
+index bd16b39..ca8fca4 100644
+--- a/g10/gpgv.c
++++ b/g10/gpgv.c
+@@ -194,7 +194,9 @@ main( int argc, char **argv )
+           break;
+         case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
+         case oOutput: opt.outfile = pargs.r.ret_str; break;
+-        case oStatusFD: set_status_fd( pargs.r.ret_int ); break;
++        case oStatusFD:
++          set_status_fd (translate_sys2libc_fd_int (pargs.r.ret_int, 1));
++          break;
+         case oLoggerFD:
+           log_set_fd (translate_sys2libc_fd_int (pargs.r.ret_int, 1));
+           break;
diff -Nru gnupg2-2.1.18/debian/patches/0041-gpg-tools-Make-trust-model-configurable-via-gpgconf.patch gnupg2-2.1.18/debian/patches/0041-gpg-tools-Make-trust-model-configurable-via-gpgconf.patch
--- gnupg2-2.1.18/debian/patches/0041-gpg-tools-Make-trust-model-configurable-via-gpgconf.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0041-gpg-tools-Make-trust-model-configurable-via-gpgconf.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,42 @@
+From: Justus Winter <justus at g10code.com>
+Date: Tue, 28 Feb 2017 13:15:42 +0100
+Subject: gpg,tools: Make trust-model configurable via gpgconf.
+
+* g10/gpg.c (gpgconf_list): Add 'trust-model'.
+* tools/gpgconf-comp.c (gc_options_gpg): Likewise.
+
+GnuPG-bug-id: 2381
+Signed-off-by: Justus Winter <justus at g10code.com>
+(cherry picked from commit ebeccd73eb85f9027f0985d77dfe901266c6ddef)
+---
+ g10/gpg.c            | 1 +
+ tools/gpgconf-comp.c | 4 ++++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/g10/gpg.c b/g10/gpg.c
+index 0c5a167..09bdf66 100644
+--- a/g10/gpg.c
++++ b/g10/gpg.c
+@@ -1845,6 +1845,7 @@ gpgconf_list (const char *configfile)
+   es_printf ("group:%lu:\n", GC_OPT_FLAG_NONE);
+   es_printf ("compliance:%lu:\"%s:\n", GC_OPT_FLAG_DEFAULT, "gnupg");
+   es_printf ("default-new-key-algo:%lu:\n", GC_OPT_FLAG_NONE);
++  es_printf ("trust-model:%lu:\n", GC_OPT_FLAG_NONE);
+ 
+   /* The next one is an info only item and should match the macros at
+      the top of keygen.c  */
+diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
+index a0d9659..cdd2586 100644
+--- a/tools/gpgconf-comp.c
++++ b/tools/gpgconf-comp.c
+@@ -716,6 +716,10 @@ static gc_option_t gc_options_gpg[] =
+      (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE,
+      NULL, NULL,
+      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
++   { "trust-model",
++     GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
++     NULL, NULL,
++     GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
+ 
+ 
+    { "Debug",
diff -Nru gnupg2-2.1.18/debian/patches/0042-gpg-tools-Make-auto-key-retrieve-configurable-via-gp.patch gnupg2-2.1.18/debian/patches/0042-gpg-tools-Make-auto-key-retrieve-configurable-via-gp.patch
--- gnupg2-2.1.18/debian/patches/0042-gpg-tools-Make-auto-key-retrieve-configurable-via-gp.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0042-gpg-tools-Make-auto-key-retrieve-configurable-via-gp.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,40 @@
+From: Justus Winter <justus at g10code.com>
+Date: Tue, 28 Feb 2017 14:59:11 +0100
+Subject: gpg,tools: Make auto-key-retrieve configurable via gpgconf.
+
+* g10/gpg.c (gpgconf_list): Add 'auto-key-retrieve'.
+* tools/gpgconf-comp.c (gc_options_gpg): Likewise.
+
+GnuPG-bug-id: 2381
+Signed-off-by: Justus Winter <justus at g10code.com>
+(cherry picked from commit d379a0174cca595204b32da9a66c513a1304e6d0)
+---
+ g10/gpg.c            | 1 +
+ tools/gpgconf-comp.c | 2 ++
+ 2 files changed, 3 insertions(+)
+
+diff --git a/g10/gpg.c b/g10/gpg.c
+index 09bdf66..2a4a0ad 100644
+--- a/g10/gpg.c
++++ b/g10/gpg.c
+@@ -1840,6 +1840,7 @@ gpgconf_list (const char *configfile)
+   es_printf ("encrypt-to:%lu:\n", GC_OPT_FLAG_NONE);
+   es_printf ("try-secret-key:%lu:\n", GC_OPT_FLAG_NONE);
+   es_printf ("auto-key-locate:%lu:\n", GC_OPT_FLAG_NONE);
++  es_printf ("auto-key-retrieve:%lu:\n", GC_OPT_FLAG_NONE);
+   es_printf ("log-file:%lu:\n", GC_OPT_FLAG_NONE);
+   es_printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
+   es_printf ("group:%lu:\n", GC_OPT_FLAG_NONE);
+diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
+index cdd2586..530c128 100644
+--- a/tools/gpgconf-comp.c
++++ b/tools/gpgconf-comp.c
+@@ -747,6 +747,8 @@ static gc_option_t gc_options_gpg[] =
+    { "auto-key-locate", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
+      "gnupg", N_("|MECHANISMS|use MECHANISMS to locate keys by mail address"),
+      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
++   { "auto-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
++     NULL, NULL, GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
+ 
+ 
+    GC_OPTION_NULL
diff -Nru gnupg2-2.1.18/debian/patches/0043-gpg-Allow-creating-keys-using-an-existing-ECC-key.patch gnupg2-2.1.18/debian/patches/0043-gpg-Allow-creating-keys-using-an-existing-ECC-key.patch
--- gnupg2-2.1.18/debian/patches/0043-gpg-Allow-creating-keys-using-an-existing-ECC-key.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0043-gpg-Allow-creating-keys-using-an-existing-ECC-key.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,204 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Wed, 1 Mar 2017 13:36:01 +0100
+Subject: gpg: Allow creating keys using an existing ECC key.
+
+* common/sexputil.c (get_pk_algo_from_canon_sexp): Remove arg R_ALGO.
+Change to return the algo id.  Reimplement using get_pk_algo_from_key.
+* g10/keygen.c (check_keygrip): Adjust for change.
+* sm/certreqgen-ui.c (check_keygrip): Ditto.
+--
+
+GnuPG-bug-id: 2976
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 2bbdeb8ee87a6c7ec211be16391a11b7c6030bed)
+---
+ common/sexputil.c  | 65 +++++++++++++++---------------------------------------
+ common/util.h      |  6 ++---
+ g10/keygen.c       | 22 +++---------------
+ sm/certreqgen-ui.c | 24 +++++++++-----------
+ 4 files changed, 34 insertions(+), 83 deletions(-)
+
+diff --git a/common/sexputil.c b/common/sexputil.c
+index 0c5c730..a8dc1a5 100644
+--- a/common/sexputil.c
++++ b/common/sexputil.c
+@@ -512,53 +512,6 @@ get_rsa_pk_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
+ }
+ 
+ 
+-/* Return the algo of a public RSA expressed as an canonical encoded
+-   S-expression.  The return value is a statically allocated
+-   string.  On error that string is set to NULL. */
+-gpg_error_t
+-get_pk_algo_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
+-                             const char **r_algo)
+-{
+-  gpg_error_t err;
+-  const unsigned char *buf, *tok;
+-  size_t buflen, toklen;
+-  int depth;
+-
+-  *r_algo = NULL;
+-
+-  buf = keydata;
+-  buflen = keydatalen;
+-  depth = 0;
+-  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
+-    return err;
+-  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
+-    return err;
+-  if (!tok || toklen != 10 || memcmp ("public-key", tok, toklen))
+-    return gpg_error (GPG_ERR_BAD_PUBKEY);
+-  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
+-    return err;
+-  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
+-    return err;
+-  if (!tok)
+-    return gpg_error (GPG_ERR_BAD_PUBKEY);
+-
+-  if (toklen == 3 && !memcmp ("rsa", tok, toklen))
+-    *r_algo = "rsa";
+-  else if (toklen == 3 && !memcmp ("dsa", tok, toklen))
+-    *r_algo = "dsa";
+-  else if (toklen == 3 && !memcmp ("elg", tok, toklen))
+-    *r_algo = "elg";
+-  else if (toklen == 5 && !memcmp ("ecdsa", tok, toklen))
+-    *r_algo = "ecdsa";
+-  else if (toklen == 5 && !memcmp ("eddsa", tok, toklen))
+-    *r_algo = "eddsa";
+-  else
+-    return gpg_error (GPG_ERR_PUBKEY_ALGO);
+-
+-  return 0;
+-}
+-
+-
+ /* Return the algo of a public KEY of SEXP. */
+ int
+ get_pk_algo_from_key (gcry_sexp_t key)
+@@ -606,3 +559,21 @@ get_pk_algo_from_key (gcry_sexp_t key)
+ 
+   return algo;
+ }
++
++
++/* This is a variant of get_pk_algo_from_key but takes an canonical
++ * encoded S-expression as input.  Returns a GCRYPT public key
++ * identiier or 0 on error.  */
++int
++get_pk_algo_from_canon_sexp (const unsigned char *keydata, size_t keydatalen)
++{
++  gcry_sexp_t sexp;
++  int algo;
++
++  if (gcry_sexp_sscan (&sexp, NULL, keydata, keydatalen))
++    return 0;
++
++  algo = get_pk_algo_from_key (sexp);
++  gcry_sexp_release (sexp);
++  return algo;
++}
+diff --git a/common/util.h b/common/util.h
+index f7a53e1..b6d7156 100644
+--- a/common/util.h
++++ b/common/util.h
+@@ -195,10 +195,10 @@ gpg_error_t get_rsa_pk_from_canon_sexp (const unsigned char *keydata,
+                                         size_t *r_nlen,
+                                         unsigned char const **r_e,
+                                         size_t *r_elen);
+-gpg_error_t get_pk_algo_from_canon_sexp (const unsigned char *keydata,
+-                                         size_t keydatalen,
+-                                         const char **r_algo);
++
+ int get_pk_algo_from_key (gcry_sexp_t key);
++int get_pk_algo_from_canon_sexp (const unsigned char *keydata,
++                                 size_t keydatalen);
+ 
+ /*-- convert.c --*/
+ int hex2bin (const char *string, void *buffer, size_t length);
+diff --git a/g10/keygen.c b/g10/keygen.c
+index 98ef29e..0180581 100644
+--- a/g10/keygen.c
++++ b/g10/keygen.c
+@@ -1838,7 +1838,7 @@ check_keygrip (ctrl_t ctrl, const char *hexgrip)
+   gpg_error_t err;
+   unsigned char *public;
+   size_t publiclen;
+-  const char *algostr;
++  int algo;
+ 
+   if (hexgrip[0] == '&')
+     hexgrip++;
+@@ -1848,26 +1848,10 @@ check_keygrip (ctrl_t ctrl, const char *hexgrip)
+     return 0;
+   publiclen = gcry_sexp_canon_len (public, 0, NULL, NULL);
+ 
+-  get_pk_algo_from_canon_sexp (public, publiclen, &algostr);
++  algo = get_pk_algo_from_canon_sexp (public, publiclen);
+   xfree (public);
+ 
+-  /* FIXME: Mapping of ECC algorithms is probably not correct. */
+-  if (!algostr)
+-    return 0;
+-  else if (!strcmp (algostr, "rsa"))
+-    return PUBKEY_ALGO_RSA;
+-  else if (!strcmp (algostr, "dsa"))
+-    return PUBKEY_ALGO_DSA;
+-  else if (!strcmp (algostr, "elg"))
+-    return PUBKEY_ALGO_ELGAMAL_E;
+-  else if (!strcmp (algostr, "ecc"))
+-    return PUBKEY_ALGO_ECDH;
+-  else if (!strcmp (algostr, "ecdsa"))
+-    return PUBKEY_ALGO_ECDSA;
+-  else if (!strcmp (algostr, "eddsa"))
+-    return PUBKEY_ALGO_EDDSA;
+-  else
+-    return 0;
++  return map_pk_gcry_to_openpgp (algo);
+ }
+ 
+ 
+diff --git a/sm/certreqgen-ui.c b/sm/certreqgen-ui.c
+index ece8668..b50d338 100644
+--- a/sm/certreqgen-ui.c
++++ b/sm/certreqgen-ui.c
+@@ -95,7 +95,7 @@ check_keygrip (ctrl_t ctrl, const char *hexgrip)
+   gpg_error_t err;
+   ksba_sexp_t public;
+   size_t publiclen;
+-  const char *algostr;
++  int algo;
+ 
+   if (hexgrip[0] == '&')
+     hexgrip++;
+@@ -105,21 +105,17 @@ check_keygrip (ctrl_t ctrl, const char *hexgrip)
+     return NULL;
+   publiclen = gcry_sexp_canon_len (public, 0, NULL, NULL);
+ 
+-  get_pk_algo_from_canon_sexp (public, publiclen, &algostr);
++  algo = get_pk_algo_from_canon_sexp (public, publiclen);
+   xfree (public);
+ 
+-  if (!algostr)
+-    return NULL;
+-  else if (!strcmp (algostr, "rsa"))
+-    return "RSA";
+-  else if (!strcmp (algostr, "dsa"))
+-    return "DSA";
+-  else if (!strcmp (algostr, "elg"))
+-    return "ELG";
+-  else if (!strcmp (algostr, "ecdsa"))
+-    return "ECDSA";
+-  else
+-    return NULL;
++  switch (algo)
++    {
++    case GCRY_PK_RSA:   return "RSA";
++    case GCRY_PK_DSA:   return "DSA";
++    case GCRY_PK_ELG:   return "ELG";
++    case GCRY_PK_EDDSA: return "ECDSA";
++    default: return NULL;
++    }
+ }
+ 
+ 
diff -Nru gnupg2-2.1.18/debian/patches/0044-gpg-Make-export-options-work-with-export-secret-keys.patch gnupg2-2.1.18/debian/patches/0044-gpg-Make-export-options-work-with-export-secret-keys.patch
--- gnupg2-2.1.18/debian/patches/0044-gpg-Make-export-options-work-with-export-secret-keys.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0044-gpg-Make-export-options-work-with-export-secret-keys.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,156 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Wed, 1 Mar 2017 14:41:47 +0100
+Subject: gpg: Make --export-options work with --export-secret-keys.
+
+* g10/export.c (export_seckeys): Add arg OPTIONS and pass it to
+do_export.
+(export_secsubkeys): Ditto.
+* g10/gpg.c (main): Pass opt.export_options to export_seckeys and
+export_secsubkeys
+--
+
+Back in the old days we did not used the export options for secret
+keys export because of a lot of duplicated code and that the old
+secring.gpg was anyway smaller that the pubring.gpg.  With 2.1 it was
+pretty easy to enable it.
+
+Reported-by: Peter Lebbing
+GnuPG-bug-id: 2973
+(cherry picked from commit 891ab23411b7f20ef37d8bde81d9857b083235df)
+---
+ doc/gpg.texi |  7 ++++---
+ g10/export.c | 31 ++++++++++++++++---------------
+ g10/gpg.c    |  4 ++--
+ g10/main.h   |  6 ++++--
+ 4 files changed, 26 insertions(+), 22 deletions(-)
+
+diff --git a/doc/gpg.texi b/doc/gpg.texi
+index b79b783..3b82b44 100644
+--- a/doc/gpg.texi
++++ b/doc/gpg.texi
+@@ -1824,7 +1824,8 @@ are available for all keyserver types, some common options are:
+   used with HKP keyservers.
+ 
+   @item auto-key-retrieve
+-  This is the same as the option @option{auto-key-retrieve}.
++  This is an obsolete alias for the option @option{auto-key-retrieve}.
++  Please do not use it; it will be removed in future versions..
+ 
+   @item honor-keyserver-url
+   When using @option{--refresh-keys}, if the key in question has a preferred
+@@ -2371,8 +2372,8 @@ The available properties are:
+ @item --export-options @code{parameters}
+ @opindex export-options
+ This is a space or comma delimited string that gives options for
+-exporting keys. Options can be prepended with a `no-' to give the
+-opposite meaning. The options are:
++exporting keys.  Options can be prepended with a `no-' to give the
++opposite meaning.  The options are:
+ 
+ @table @asis
+ 
+diff --git a/g10/export.c b/g10/export.c
+index 8668126..207f994 100644
+--- a/g10/export.c
++++ b/g10/export.c
+@@ -247,16 +247,17 @@ export_pubkeys (ctrl_t ctrl, strlist_t users, unsigned int options,
+ /*
+  * Export secret keys (to stdout or to --output FILE).
+  *
+- * Depending on opt.armor the output is armored.  If USERS is NULL,
+- * all secret keys will be exported.  STATS is either an export stats
+- * object for update or NULL.
++ * Depending on opt.armor the output is armored.  OPTIONS are defined
++ * in main.h.  If USERS is NULL, all secret keys will be exported.
++ * STATS is either an export stats object for update or NULL.
+  *
+  * This function is the core of "gpg --export-secret-keys".
+  */
+ int
+-export_seckeys (ctrl_t ctrl, strlist_t users, export_stats_t stats)
++export_seckeys (ctrl_t ctrl, strlist_t users, unsigned int options,
++                export_stats_t stats)
+ {
+-  return do_export (ctrl, users, 1, 0, stats);
++  return do_export (ctrl, users, 1, options, stats);
+ }
+ 
+ 
+@@ -264,16 +265,18 @@ export_seckeys (ctrl_t ctrl, strlist_t users, export_stats_t stats)
+  * Export secret sub keys (to stdout or to --output FILE).
+  *
+  * This is the same as export_seckeys but replaces the primary key by
+- * a stub key.  Depending on opt.armor the output is armored.  If
+- * USERS is NULL, all secret subkeys will be exported.  STATS is
+- * either an export stats object for update or NULL.
++ * a stub key.  Depending on opt.armor the output is armored.  OPTIONS
++ * are defined in main.h.  If USERS is NULL, all secret subkeys will
++ * be exported.  STATS is either an export stats object for update or
++ * NULL.
+  *
+  * This function is the core of "gpg --export-secret-subkeys".
+  */
+ int
+-export_secsubkeys (ctrl_t ctrl, strlist_t users, export_stats_t stats)
++export_secsubkeys (ctrl_t ctrl, strlist_t users, unsigned int options,
++                   export_stats_t stats)
+ {
+-  return do_export (ctrl, users, 2, 0, stats);
++  return do_export (ctrl, users, 2, options, stats);
+ }
+ 
+ 
+@@ -1969,11 +1972,9 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
+         }
+ 
+       /* Always do the cleaning on the public key part if requested.
+-         Note that we don't yet set this option if we are exporting
+-         secret keys.  Note that both export-clean and export-minimal
+-         only apply to UID sigs (0x10, 0x11, 0x12, and 0x13).  A
+-         designated revocation is never stripped, even with
+-         export-minimal set.  */
++       * Note that both export-clean and export-minimal only apply to
++       * UID sigs (0x10, 0x11, 0x12, and 0x13).  A designated
++       * revocation is never stripped, even with export-minimal set.  */
+       if ((options & EXPORT_CLEAN))
+         clean_key (keyblock, opt.verbose, (options&EXPORT_MINIMAL), NULL, NULL);
+ 
+diff --git a/g10/gpg.c b/g10/gpg.c
+index 2a4a0ad..5a880fd 100644
+--- a/g10/gpg.c
++++ b/g10/gpg.c
+@@ -4546,7 +4546,7 @@ main (int argc, char **argv)
+ 	    add_to_strlist2( &sl, *argv, utf8_strings );
+         {
+           export_stats_t stats = export_new_stats ();
+-          export_seckeys (ctrl, sl, stats);
++          export_seckeys (ctrl, sl, opt.export_options, stats);
+           export_print_stats (stats);
+           export_release_stats (stats);
+         }
+@@ -4559,7 +4559,7 @@ main (int argc, char **argv)
+ 	    add_to_strlist2( &sl, *argv, utf8_strings );
+         {
+           export_stats_t stats = export_new_stats ();
+-          export_secsubkeys (ctrl, sl, stats);
++          export_secsubkeys (ctrl, sl, opt.export_options, stats);
+           export_print_stats (stats);
+           export_release_stats (stats);
+         }
+diff --git a/g10/main.h b/g10/main.h
+index 5ed501b..6837e98 100644
+--- a/g10/main.h
++++ b/g10/main.h
+@@ -397,8 +397,10 @@ gpg_error_t parse_and_set_export_filter (const char *string);
+ 
+ int export_pubkeys (ctrl_t ctrl, strlist_t users, unsigned int options,
+                     export_stats_t stats);
+-int export_seckeys (ctrl_t ctrl, strlist_t users, export_stats_t stats);
+-int export_secsubkeys (ctrl_t ctrl, strlist_t users, export_stats_t stats);
++int export_seckeys (ctrl_t ctrl, strlist_t users, unsigned int options,
++                    export_stats_t stats);
++int export_secsubkeys (ctrl_t ctrl, strlist_t users, unsigned int options,
++                       export_stats_t stats);
+ 
+ gpg_error_t export_pubkey_buffer (ctrl_t ctrl, const char *keyspec,
+                                   unsigned int options,
diff -Nru gnupg2-2.1.18/debian/patches/0045-common-tools-Always-escape-newlines-when-escaping-da.patch gnupg2-2.1.18/debian/patches/0045-common-tools-Always-escape-newlines-when-escaping-da.patch
--- gnupg2-2.1.18/debian/patches/0045-common-tools-Always-escape-newlines-when-escaping-da.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0045-common-tools-Always-escape-newlines-when-escaping-da.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,63 @@
+From: Justus Winter <justus at g10code.com>
+Date: Wed, 1 Mar 2017 17:47:47 +0100
+Subject: common,tools: Always escape newlines when escaping data.
+
+* common/stringhelp.c (do_percent_escape): Always escape newlines.
+* tools/gpgconf-comp.c (gc_percent_escape): Likewise.
+--
+Newlines always pose a problem for a line-based communication format.
+
+GnuPG-bug-id: 2387
+Signed-off-by: Justus Winter <justus at g10code.com>
+(cherry picked from commit e064c75b08a523f738108428fe0c417a46e66238)
+---
+ common/stringhelp.c  | 10 +++++++++-
+ tools/gpgconf-comp.c |  7 +++++++
+ 2 files changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/common/stringhelp.c b/common/stringhelp.c
+index dea2212..0abfa3d 100644
+--- a/common/stringhelp.c
++++ b/common/stringhelp.c
+@@ -1052,7 +1052,8 @@ do_percent_escape (const char *str, const char *extra, int die)
+     return NULL;
+ 
+   for (i=j=0; str[i]; i++)
+-    if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i])))
++    if (str[i] == ':' || str[i] == '%' || str[i] == '\n'
++        || (extra && strchr (extra, str[i])))
+       j++;
+   if (die)
+     ptr = xmalloc (i + 2 * j + 1);
+@@ -1077,6 +1078,13 @@ do_percent_escape (const char *str, const char *extra, int die)
+ 	  ptr[i++] = '2';
+ 	  ptr[i++] = '5';
+ 	}
++      else if (*str == '\n')
++	{
++	  /* The newline is problematic in a line-based format.  */
++	  ptr[i++] = '%';
++	  ptr[i++] = '0';
++	  ptr[i++] = 'a';
++	}
+       else if (extra && strchr (extra, *str))
+         {
+ 	  ptr[i++] = '%';
+diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
+index 530c128..9358e2e 100644
+--- a/tools/gpgconf-comp.c
++++ b/tools/gpgconf-comp.c
+@@ -1490,6 +1490,13 @@ gc_percent_escape (const char *src)
+ 	  *(dst++) = '2';
+ 	  *(dst++) = 'c';
+ 	}
++      else if (*src == '\n')
++	{
++	  /* The newline is problematic in a line-based format.  */
++	  *(dst++) = '%';
++	  *(dst++) = '0';
++	  *(dst++) = 'a';
++	}
+       else
+ 	*(dst++) = *(src);
+       src++;
diff -Nru gnupg2-2.1.18/debian/patches/0046-g10-Signal-an-error-when-trying-to-revoke-non-exista.patch gnupg2-2.1.18/debian/patches/0046-g10-Signal-an-error-when-trying-to-revoke-non-exista.patch
--- gnupg2-2.1.18/debian/patches/0046-g10-Signal-an-error-when-trying-to-revoke-non-exista.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0046-g10-Signal-an-error-when-trying-to-revoke-non-exista.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,53 @@
+From: Justus Winter <justus at g10code.com>
+Date: Thu, 2 Mar 2017 11:39:00 +0100
+Subject: g10: Signal an error when trying to revoke non-existant UID.
+
+* g10/keyedit.c (keyedit_quick_revuid): Signal an error when trying to
+revoke non-existant UID.
+* tests/openpgp/quick-key-manipulation.scm: Test that.
+
+GnuPG-bug-id: 2962
+Signed-off-by: Justus Winter <justus at g10code.com>
+(cherry picked from commit 62d21a4ab4029b32ea129f1cf3a0e1f22e2fb7b0)
+---
+ g10/keyedit.c                            | 2 ++
+ tests/openpgp/quick-key-manipulation.scm | 6 ++++++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/g10/keyedit.c b/g10/keyedit.c
+index 1456d28..a477e92 100644
+--- a/g10/keyedit.c
++++ b/g10/keyedit.c
+@@ -3053,6 +3053,8 @@ keyedit_quick_revuid (ctrl_t ctrl, const char *username, const char *uidtorev)
+         }
+     }
+ 
++  log_error (_("User ID revocation failed: %s\n"), gpg_strerror (GPG_ERR_NOT_FOUND));
++
+  leave:
+   release_kbnode (keyblock);
+   keydb_release (kdbhd);
+diff --git a/tests/openpgp/quick-key-manipulation.scm b/tests/openpgp/quick-key-manipulation.scm
+index d43f7b5..ae1d0b9 100755
+--- a/tests/openpgp/quick-key-manipulation.scm
++++ b/tests/openpgp/quick-key-manipulation.scm
+@@ -36,6 +36,7 @@
+ 
+ (define alpha "Alpha <alpha at invalid.example.net>")
+ (define bravo "Bravo <bravo at invalid.example.net>")
++(define charlie "Charlie <charlie at invalid.example.net>")
+ 
+ (define (key-data key)
+   (filter (lambda (x) (or (string=? (car x) "pub")
+@@ -78,6 +79,11 @@
+ (info "Checking that we can revoke a user ID...")
+ (call-check `(, at GPG --quick-revoke-uid ,(exact bravo) ,alpha))
+ 
++(info "Checking that we get an error revoking a non-existant user ID.")
++(catch '()
++       (call-check `(, at GPG --quick-revoke-uid ,(exact bravo) ,charlie))
++       (error "Expected an error, but get none."))
++
+ (assert (= 1 (count-uids-of-secret-key bravo)))
+ 
+ (info "Checking that we can change the expiration time.")
diff -Nru gnupg2-2.1.18/debian/patches/0047-gpg-Fix-possible-segv-when-attribute-packets-are-fil.patch gnupg2-2.1.18/debian/patches/0047-gpg-Fix-possible-segv-when-attribute-packets-are-fil.patch
--- gnupg2-2.1.18/debian/patches/0047-gpg-Fix-possible-segv-when-attribute-packets-are-fil.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0047-gpg-Fix-possible-segv-when-attribute-packets-are-fil.patch	2017-05-08 16:44:17.000000000 -0400
@@ -0,0 +1,58 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Fri, 3 Mar 2017 09:50:40 +0100
+Subject: gpg: Fix possible segv when attribute packets are filtered.
+
+* g10/import.c (impex_filter_getval): Handle PKT_ATTRIBUTE the same as
+PKT_USER_ID
+(apply_drop_sig_filter): Ditto.
+--
+
+The old code was plainly wrong in that it considered PKT_ATTRIBUTE to
+use a PKT_signature object.
+
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 5f6f3f5cae8a95ed469129f9677782c17951dab3)
+---
+ g10/import.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/g10/import.c b/g10/import.c
+index b6c04dc..4e6f692 100644
+--- a/g10/import.c
++++ b/g10/import.c
+@@ -1173,7 +1173,8 @@ impex_filter_getval (void *cookie, const char *propname)
+   static char numbuf[20];
+   const char *result;
+ 
+-  if (node->pkt->pkttype == PKT_USER_ID)
++  if (node->pkt->pkttype == PKT_USER_ID
++      || node->pkt->pkttype == PKT_ATTRIBUTE)
+     {
+       if (!strcmp (propname, "uid"))
+         result = node->pkt->pkt.user_id->name;
+@@ -1191,8 +1192,7 @@ impex_filter_getval (void *cookie, const char *propname)
+       else
+         result = NULL;
+     }
+-  else if (node->pkt->pkttype == PKT_SIGNATURE
+-           || node->pkt->pkttype == PKT_ATTRIBUTE)
++  else if (node->pkt->pkttype == PKT_SIGNATURE)
+     {
+       PKT_signature *sig = node->pkt->pkt.signature;
+ 
+@@ -1313,12 +1313,12 @@ apply_drop_sig_filter (kbnode_t keyblock, recsel_expr_t selector)
+       if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+           || node->pkt->pkttype == PKT_SECRET_SUBKEY)
+         break; /* ready.  */
+-      if (node->pkt->pkttype == PKT_USER_ID)
++      if (node->pkt->pkttype == PKT_USER_ID
++          || node->pkt->pkttype == PKT_ATTRIBUTE)
+         active = 1;
+       if (!active)
+         continue;
+-      if (node->pkt->pkttype != PKT_SIGNATURE
+-          && node->pkt->pkttype != PKT_ATTRIBUTE)
++      if (node->pkt->pkttype != PKT_SIGNATURE)
+         continue;
+ 
+       sig = node->pkt->pkt.signature;
diff -Nru gnupg2-2.1.18/debian/patches/0048-gpg-Fix-attempt-to-double-free-an-UID-structure.patch gnupg2-2.1.18/debian/patches/0048-gpg-Fix-attempt-to-double-free-an-UID-structure.patch
--- gnupg2-2.1.18/debian/patches/0048-gpg-Fix-attempt-to-double-free-an-UID-structure.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0048-gpg-Fix-attempt-to-double-free-an-UID-structure.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,59 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Sun, 5 Mar 2017 23:24:15 +0100
+Subject: gpg: Fix attempt to double free an UID structure.
+
+* g10/getkey.c (get_best_pubkey_byname): Set released .UID to NULL.
+--
+
+Phil Pennock reported an assertion failure when doing
+
+  % gpg --auto-key-locate dane --locate-keys someone
+  gpg: Ohhhh jeeee: Assertion "uid->ref > 0" in \
+         free_user_id failed (free-packet.c:310)
+
+on his keyring.  This patch is not tested but a good guess.
+
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 4a130bbc2c2f4be6e8c6357512a943f435ade28f)
+---
+ g10/getkey.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/g10/getkey.c b/g10/getkey.c
+index e39de28..21dcf08 100644
+--- a/g10/getkey.c
++++ b/g10/getkey.c
+@@ -1592,8 +1592,10 @@ get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk,
+   if (is_valid_mailbox (name) && ctx)
+     {
+       /* Rank results and return only the most relevant key.  */
+-      struct pubkey_cmp_cookie best = { 0 }, new;
+-      KBNODE new_keyblock;
++      struct pubkey_cmp_cookie best = { 0 };
++      struct pubkey_cmp_cookie new;
++      kbnode_t new_keyblock;
++
+       while (getkey_next (ctx, &new.key, &new_keyblock) == 0)
+         {
+           int diff = pubkey_cmp (ctrl, name, &best, &new, new_keyblock);
+@@ -1610,17 +1612,20 @@ get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk,
+               /* Old key is better.  */
+               release_public_key_parts (&new.key);
+               free_user_id (new.uid);
++              new.uid = NULL;
+             }
+           else
+             {
+               /* A tie.  Keep the old key.  */
+               release_public_key_parts (&new.key);
+               free_user_id (new.uid);
++              new.uid = NULL;
+             }
+         }
+       getkey_end (ctx);
+       ctx = NULL;
+       free_user_id (best.uid);
++      best.uid = NULL;
+ 
+       if (best.valid)
+         {
diff -Nru gnupg2-2.1.18/debian/patches/0049-doc-Add-a-note-to-the-trust-model-direct.patch gnupg2-2.1.18/debian/patches/0049-doc-Add-a-note-to-the-trust-model-direct.patch
--- gnupg2-2.1.18/debian/patches/0049-doc-Add-a-note-to-the-trust-model-direct.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0049-doc-Add-a-note-to-the-trust-model-direct.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,75 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Wed, 8 Mar 2017 10:46:09 +0100
+Subject: doc: Add a note to the trust model direct.
+
+* doc/gpg.texi (GPG Configuration Options): Add note.  Chnage Index
+from trust-mode:foo to trust-model:foo.
+
+(cherry picked from commit f0257b4a86b73f5b956028e68590b6d2a23ea4da)
+---
+ doc/gpg.texi | 20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+diff --git a/doc/gpg.texi b/doc/gpg.texi
+index 3b82b44..d658737 100644
+--- a/doc/gpg.texi
++++ b/doc/gpg.texi
+@@ -1600,17 +1600,17 @@ Set what trust model GnuPG should follow. The models are:
+ @table @asis
+ 
+   @item pgp
+-  @opindex trust-mode:pgp
++  @opindex trust-model:pgp
+   This is the Web of Trust combined with trust signatures as used in PGP
+   5.x and later. This is the default trust model when creating a new
+   trust database.
+ 
+   @item classic
+-  @opindex trust-mode:classic
++  @opindex trust-model:classic
+   This is the standard Web of Trust as introduced by PGP 2.
+ 
+   @item tofu
+-  @opindex trust-mode:tofu
++  @opindex trust-model:tofu
+   @anchor{trust-model-tofu}
+   TOFU stands for Trust On First Use.  In this trust model, the first
+   time a key is seen, it is memorized.  If later another key is seen
+@@ -1656,7 +1656,7 @@ Set what trust model GnuPG should follow. The models are:
+   @code{undefined} trust level is returned.
+ 
+   @item tofu+pgp
+-  @opindex trust-mode:tofu+pgp
++  @opindex trust-model:tofu+pgp
+   This trust model combines TOFU with the Web of Trust.  This is done
+   by computing the trust level for each model and then taking the
+   maximum trust level where the trust levels are ordered as follows:
+@@ -1669,12 +1669,16 @@ Set what trust model GnuPG should follow. The models are:
+   which some security-conscious users don't like.
+ 
+   @item direct
+-  @opindex trust-mode:direct
++  @opindex trust-model:direct
+   Key validity is set directly by the user and not calculated via the
+-  Web of Trust.
++  Web of Trust.  This model is soley based on the key and does
++  not distinguish user IDs.  Note that when changing to another trust
++  model the trust values assigned to a key are transformed into
++  ownertrust values, which also indicate how you trust the owner of
++  the key to sign other keys.
+ 
+   @item always
+-  @opindex trust-mode:always
++  @opindex trust-model:always
+   Skip key validation and assume that used keys are always fully
+   valid. You generally won't use this unless you are using some
+   external validation scheme. This option also suppresses the
+@@ -1684,7 +1688,7 @@ Set what trust model GnuPG should follow. The models are:
+   disabled keys.
+ 
+   @item auto
+-  @opindex trust-mode:auto
++  @opindex trust-model:auto
+   Select the trust model depending on whatever the internal trust
+   database says. This is the default model if such a database already
+   exists.
diff -Nru gnupg2-2.1.18/debian/patches/0050-gpg-Flush-stdout-before-printing-stats-with-check-si.patch gnupg2-2.1.18/debian/patches/0050-gpg-Flush-stdout-before-printing-stats-with-check-si.patch
--- gnupg2-2.1.18/debian/patches/0050-gpg-Flush-stdout-before-printing-stats-with-check-si.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0050-gpg-Flush-stdout-before-printing-stats-with-check-si.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,37 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Mon, 13 Mar 2017 17:42:08 +0100
+Subject: gpg: Flush stdout before printing stats with --check-sigs.
+
+* g10/keylist.c (print_signature_stats): Flush stdout.
+(list_keyblock_colon): Use es_flush instead of fflush.
+
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 9a77b3b6e41f97b1209ad61c04b3dd33242ecae8)
+---
+ g10/keylist.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/g10/keylist.c b/g10/keylist.c
+index abdcb9f..4078053 100644
+--- a/g10/keylist.c
++++ b/g10/keylist.c
+@@ -465,6 +465,10 @@ print_signature_stats (struct keylist_context *s)
+   if (!s->check_sigs)
+     return;  /* Signature checking was not requested.  */
+ 
++  /* Better flush stdout so that the stats are always printed after
++   * the output.  */
++  es_fflush (es_stdout);
++
+   if (s->good_sigs)
+     log_info (ngettext("%d good signature\n",
+                        "%d good signatures\n", s->good_sigs), s->good_sigs);
+@@ -1447,7 +1451,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
+ 	    {
+ 	      PKT_public_key *signer_pk = NULL;
+ 
+-	      fflush (stdout);
++	      es_fflush (es_stdout);
+ 	      if (opt.no_sig_cache)
+ 		signer_pk = xmalloc_clear (sizeof (PKT_public_key));
+ 
diff -Nru gnupg2-2.1.18/debian/patches/0051-dirmngr-Ignore-warning-alerts-in-the-GNUTLS-handshak.patch gnupg2-2.1.18/debian/patches/0051-dirmngr-Ignore-warning-alerts-in-the-GNUTLS-handshak.patch
--- gnupg2-2.1.18/debian/patches/0051-dirmngr-Ignore-warning-alerts-in-the-GNUTLS-handshak.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0051-dirmngr-Ignore-warning-alerts-in-the-GNUTLS-handshak.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,44 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Fri, 17 Mar 2017 12:46:09 +0100
+Subject: dirmngr: Ignore warning alerts in the GNUTLS handshake.
+
+* dirmngr/http.c (send_request) [GNUTLS]: Don't bail out on warning
+alerts.
+--
+
+GnuPG-bug-id: 2833
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 69c521df422a6c9a6b0a93e45c9373a8b6ceb28e)
+---
+ dirmngr/http.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/dirmngr/http.c b/dirmngr/http.c
+index fe9c3c7..c9c16df 100644
+--- a/dirmngr/http.c
++++ b/dirmngr/http.c
+@@ -1847,6 +1847,7 @@ send_request (http_t hd, const char *httphost, const char *auth,
+       gnutls_transport_set_push_function (hd->session->tls_session,
+                                           my_gnutls_write);
+ 
++    handshake_again:
+       do
+         {
+           rc = gnutls_handshake (hd->session->tls_session);
+@@ -1862,10 +1863,15 @@ send_request (http_t hd, const char *httphost, const char *auth,
+ 
+               alertno = gnutls_alert_get (hd->session->tls_session);
+               alertstr = gnutls_alert_get_name (alertno);
+-              log_info ("TLS handshake failed: %s (alert %d)\n",
++              log_info ("TLS handshake %s: %s (alert %d)\n",
++                        rc == GNUTLS_E_WARNING_ALERT_RECEIVED
++                        ? "warning" : "failed",
+                         alertstr, (int)alertno);
+               if (alertno == GNUTLS_A_UNRECOGNIZED_NAME && server)
+                 log_info ("  (sent server name '%s')\n", server);
++
++              if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED)
++                goto handshake_again;
+             }
+           else
+             log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
diff -Nru gnupg2-2.1.18/debian/patches/0052-gpg-Make-sure-the-conflict-set-includes-the-current-.patch gnupg2-2.1.18/debian/patches/0052-gpg-Make-sure-the-conflict-set-includes-the-current-.patch
--- gnupg2-2.1.18/debian/patches/0052-gpg-Make-sure-the-conflict-set-includes-the-current-.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0052-gpg-Make-sure-the-conflict-set-includes-the-current-.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,72 @@
+From: "Neal H. Walfield" <neal at g10code.com>
+Date: Fri, 17 Mar 2017 13:36:51 +0100
+Subject: gpg: Make sure the conflict set includes the current key.
+
+* g10/tofu.c (get_trust): Sanity check CONFLICT_SET after calling
+get_policy.  If POLICY is 'auto' and the default policy is 'ask', make
+sure CONFLICT_SET includes the current key.
+
+--
+Signed-off-by: Neal H. Walfield <neal at g10code.com>
+GnuPG-bug-id: 2959
+Debian-bug-id: 854829
+
+Signed-off-by: Neal H. Walfield <neal at g10code.com>
+(cherry picked from commit b1106b4d640325c60a7212a4a44e4f67c0e3312d)
+---
+ g10/tofu.c | 28 +++++++++++++++++++++++++---
+ 1 file changed, 25 insertions(+), 3 deletions(-)
+
+diff --git a/g10/tofu.c b/g10/tofu.c
+index 449e921..39457a5 100644
+--- a/g10/tofu.c
++++ b/g10/tofu.c
+@@ -2304,9 +2304,14 @@ build_conflict_set (tofu_dbs_t dbs,
+ 
+ 
+ /* Return the effective policy for the binding <FINGERPRINT, EMAIL>
+- * (email has already been normalized) and any conflict information in
+- * *CONFLICT_SETP, if CONFLICT_SETP is not NULL.  Returns
+- * _tofu_GET_POLICY_ERROR if an error occurs.
++ * (email has already been normalized).  Returns
++ * _tofu_GET_POLICY_ERROR if an error occurs.  Returns any conflict
++ * information in *CONFLICT_SETP if CONFLICT_SETP is not NULL and the
++ * returned policy is TOFU_POLICY_ASK (consequently, if there is a
++ * conflict, but the user set the policy to good *CONFLICT_SETP will
++ * empty).  Note: as per build_conflict_set, which is used to build
++ * the conflict information, the conflict information includes the
++ * current user id as the first element of the linked list.
+  *
+  * This function registers the binding in the bindings table if it has
+  * not yet been registered.
+@@ -2689,6 +2694,15 @@ get_trust (ctrl_t ctrl, PKT_public_key *pk,
+   policy = get_policy (dbs, pk, fingerprint, user_id, email,
+                        &conflict_set, now);
+ 
++  if (policy == TOFU_POLICY_ASK)
++    /* The conflict set should always contain at least one element:
++     * the current key.  */
++    log_assert (conflict_set);
++  else
++    /* If the policy is not TOFU_POLICY_ASK, then conflict_set will be
++     * NULL.  */
++    log_assert (! conflict_set);
++
+   /* If the key is ultimately trusted, there is nothing to do.  */
+   {
+     u32 kid[2];
+@@ -2710,6 +2724,14 @@ get_trust (ctrl_t ctrl, PKT_public_key *pk,
+                    " auto (default: %s).\n",
+ 		   fingerprint, email,
+ 		   tofu_policy_str (opt.tofu_default_policy));
++
++      if (policy == TOFU_POLICY_ASK)
++        /* The default policy is ASK, but there is no conflict (policy
++         * was 'auto').  In this case, we need to make sure the
++         * conflict set includes at least the current user id.  */
++        {
++          add_to_strlist (&conflict_set, fingerprint);
++        }
+     }
+   switch (policy)
+     {
diff -Nru gnupg2-2.1.18/debian/patches/0053-dirmngr-Load-the-hosts-file-into-libdns.patch gnupg2-2.1.18/debian/patches/0053-dirmngr-Load-the-hosts-file-into-libdns.patch
--- gnupg2-2.1.18/debian/patches/0053-dirmngr-Load-the-hosts-file-into-libdns.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0053-dirmngr-Load-the-hosts-file-into-libdns.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,60 @@
+From: Justus Winter <justus at g10code.com>
+Date: Tue, 21 Mar 2017 14:18:25 +0100
+Subject: dirmngr: Load the hosts file into libdns.
+
+* dirmngr/dns-stuff.c (libdns_init): Actually load the hosts file into
+libdns.
+--
+
+Previously, connecting to key servers specified in /etc/hosts was not
+possible because libdns' hosts structure was initialized, but not
+filled with the content of the hosts file.
+
+GnuPG-bug-id: 2977
+Signed-off-by: Justus Winter <justus at g10code.com>
+(cherry picked from commit 88f1505f0613894d5544290a170119eb538921e5)
+---
+ dirmngr/dns-stuff.c | 26 +++++++++++++++++++++++++-
+ 1 file changed, 25 insertions(+), 1 deletion(-)
+
+diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c
+index bc2e071..35e6c82 100644
+--- a/dirmngr/dns-stuff.c
++++ b/dirmngr/dns-stuff.c
+@@ -533,11 +533,35 @@ libdns_init (void)
+   ld.hosts = dns_hosts_open (&derr);
+   if (!ld.hosts)
+     {
+-      log_error ("failed to load hosts file: %s\n", gpg_strerror (err));
+       err = libdns_error_to_gpg_error (derr);
++      log_error ("failed to initialize hosts file: %s\n", gpg_strerror (err));
+       goto leave;
+     }
+ 
++
++  {
++#if HAVE_W32_SYSTEM
++    char *hosts_path = xtryasprintf ("%s\System32\drivers\etc\hosts",
++                                     getenv ("SystemRoot"));
++    if (! hosts_path)
++      {
++        err = gpg_error_from_syserror ();
++        goto leave;
++      }
++
++    derr = dns_hosts_loadpath (ld.hosts, hosts_path);
++    xfree (hosts_path);
++#else
++    derr = dns_hosts_loadpath (ld.hosts, "/etc/hosts");
++#endif
++    if (derr)
++      {
++        err = libdns_error_to_gpg_error (derr);
++        log_error ("failed to load hosts file: %s\n", gpg_strerror (err));
++        goto leave;
++      }
++  }
++
+   /* dns_hints_local for stub mode, dns_hints_root for recursive.  */
+   ld.hints = (recursive_resolver
+               ? dns_hints_root  (ld.resolv_conf, &derr)
diff -Nru gnupg2-2.1.18/debian/patches/0054-dirmngr-Fix-error-handling.patch gnupg2-2.1.18/debian/patches/0054-dirmngr-Fix-error-handling.patch
--- gnupg2-2.1.18/debian/patches/0054-dirmngr-Fix-error-handling.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0054-dirmngr-Fix-error-handling.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,26 @@
+From: Justus Winter <justus at g10code.com>
+Date: Tue, 21 Mar 2017 14:22:13 +0100
+Subject: dirmngr: Fix error handling.
+
+* dirmngr/dns-stuff.c (libdns_init): Convert error before printing it.
+
+Signed-off-by: Justus Winter <justus at g10code.com>
+(cherry picked from commit 483c1288a8f86dc6bf93d0d3f2865ecc246aecba)
+---
+ dirmngr/dns-stuff.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c
+index 35e6c82..c79a9c7 100644
+--- a/dirmngr/dns-stuff.c
++++ b/dirmngr/dns-stuff.c
+@@ -568,8 +568,8 @@ libdns_init (void)
+               : dns_hints_local (ld.resolv_conf, &derr));
+   if (!ld.hints)
+     {
+-      log_error ("failed to load DNS hints: %s\n", gpg_strerror (err));
+       err = libdns_error_to_gpg_error (derr);
++      log_error ("failed to load DNS hints: %s\n", gpg_strerror (err));
+       goto leave;
+     }
+ 
diff -Nru gnupg2-2.1.18/debian/patches/0055-common-Implicitly-do-a-gpgconf-create-socketdir.patch gnupg2-2.1.18/debian/patches/0055-common-Implicitly-do-a-gpgconf-create-socketdir.patch
--- gnupg2-2.1.18/debian/patches/0055-common-Implicitly-do-a-gpgconf-create-socketdir.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0055-common-Implicitly-do-a-gpgconf-create-socketdir.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,65 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Thu, 23 Mar 2017 09:38:19 +0100
+Subject: common: Implicitly do a gpgconf --create-socketdir.
+
+* common/homedir.c (_gnupg_socketdir_internal): Create the
+sub-directory.
+--
+
+Although there is no auto cleanup (yet) this should be helpful.  Let's
+see whether possibly leaving stale directories around is better than
+running into trouble when --create-socketdir was not used.
+
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 26086b362ff47d21b1abefaf674a6464bf0a8921)
+---
+ common/homedir.c | 25 ++++++++++++++++++-------
+ 1 file changed, 18 insertions(+), 7 deletions(-)
+
+diff --git a/common/homedir.c b/common/homedir.c
+index 6b40bb6..c41cbdc 100644
+--- a/common/homedir.c
++++ b/common/homedir.c
+@@ -542,7 +542,7 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info)
+ 
+   /* If a non default homedir is used, we check whether an
+    * corresponding sub directory below the socket dir is available
+-   * and use that.  We has the non default homedir to keep the new
++   * and use that.  We hash the non default homedir to keep the new
+    * subdir short enough.  */
+   if (non_default_homedir)
+     {
+@@ -566,16 +566,27 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info)
+           goto leave;
+         }
+ 
+-      /* Stat that directory and check constraints.  Note that we
+-       * do not auto create such a directory because we would not
+-       * have a way to remove it.  Thus the directory needs to be
+-       * pre-created.  The command
+-       *    gpgconf --create-socketdir
+-       * can be used tocreate that directory.  */
++      /* Stat that directory and check constraints.
++       * The command
++       *    gpgconf --remove-socketdir
++       * can be used to remove that directory.  */
+       if (stat (name, &sb))
+         {
+           if (errno != ENOENT)
+             *r_info |= 1; /* stat failed. */
++          else if (!skip_checks)
++            {
++              /* Try to create the directory and check again.  */
++              if (gnupg_mkdir (name, "-rwx"))
++                *r_info |= 16; /* mkdir failed.  */
++              else if (stat (prefix, &sb))
++                {
++                  if (errno != ENOENT)
++                    *r_info |= 1; /* stat failed. */
++                  else
++                    *r_info |= 64; /* Subdir does not exist.  */
++                }
++            }
+           else
+             *r_info |= 64; /* Subdir does not exist.  */
+           if (!skip_checks)
diff -Nru gnupg2-2.1.18/debian/patches/0056-common-Fix-connecting-to-the-agent.patch gnupg2-2.1.18/debian/patches/0056-common-Fix-connecting-to-the-agent.patch
--- gnupg2-2.1.18/debian/patches/0056-common-Fix-connecting-to-the-agent.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0056-common-Fix-connecting-to-the-agent.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,34 @@
+From: Justus Winter <justus at g10code.com>
+Date: Mon, 27 Mar 2017 16:14:20 +0200
+Subject: common: Fix connecting to the agent.
+
+* common/homedir.c (_gnupg_socketdir_internal): Fix error handling.
+--
+
+Prior to 26086b36 the non-existance of the socket directory was
+considered an error if a non-default home directory is used.  Since
+26086b36 we now create the directory on demand, but the function still
+returned the fallback path.  This made the agent bind the socket in
+the socket directory, and the client trying to connect to the socket
+in the home directory.
+
+Fixes-commit: 26086b362ff47d21b1abefaf674a6464bf0a8921
+Signed-off-by: Justus Winter <justus at g10code.com>
+(cherry picked from commit caf00915532e6e8e509738962964edcd14fb0654)
+---
+ common/homedir.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/common/homedir.c b/common/homedir.c
+index c41cbdc..4571aac 100644
+--- a/common/homedir.c
++++ b/common/homedir.c
+@@ -586,6 +586,8 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info)
+                   else
+                     *r_info |= 64; /* Subdir does not exist.  */
+                 }
++              else
++                goto leave; /* Success!  */
+             }
+           else
+             *r_info |= 64; /* Subdir does not exist.  */
diff -Nru gnupg2-2.1.18/debian/patches/0057-g10-Fix-memory-leak.patch gnupg2-2.1.18/debian/patches/0057-g10-Fix-memory-leak.patch
--- gnupg2-2.1.18/debian/patches/0057-g10-Fix-memory-leak.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0057-g10-Fix-memory-leak.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,33 @@
+From: Justus Winter <justus at g10code.com>
+Date: Tue, 28 Mar 2017 12:10:28 +0200
+Subject: g10: Fix memory leak.
+
+* g10/decrypt-data.c (decrypt_data): Free 'filename'.
+
+Signed-off-by: Justus Winter <justus at g10code.com>
+(cherry picked from commit 6d3edfd972c1114f43f6b35773dc25e0256f48f4)
+---
+ g10/decrypt-data.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/g10/decrypt-data.c b/g10/decrypt-data.c
+index 585b150..f5843d6 100644
+--- a/g10/decrypt-data.c
++++ b/g10/decrypt-data.c
+@@ -222,7 +222,7 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
+ 
+   if (opt.unwrap_encryption)
+     {
+-      char *filename;
++      char *filename = NULL;
+       estream_t fp;
+       rc = get_output_file ("", 0, ed->buf, &filename, &fp);
+       if (! rc)
+@@ -248,6 +248,7 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
+           if (afx)
+             release_armor_context (afx);
+         }
++      xfree (filename);
+     }
+   else
+     proc_packets (ctrl, procctx, ed->buf );
diff -Nru gnupg2-2.1.18/debian/patches/0058-common-Avoid-undefined-behavior.patch gnupg2-2.1.18/debian/patches/0058-common-Avoid-undefined-behavior.patch
--- gnupg2-2.1.18/debian/patches/0058-common-Avoid-undefined-behavior.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0058-common-Avoid-undefined-behavior.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,26 @@
+From: Justus Winter <justus at g10code.com>
+Date: Thu, 30 Mar 2017 15:44:35 +0200
+Subject: common: Avoid undefined behavior.
+
+* common/iobuf.c (iobuf_read_line): Do not consider 'length' if
+'buffer' is NULL.
+
+Signed-off-by: Justus Winter <justus at g10code.com>
+(cherry picked from commit 214fa9012296d796b78f1a3106d656639cf50aef)
+---
+ common/iobuf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/common/iobuf.c b/common/iobuf.c
+index d346027..b8baf7f 100644
+--- a/common/iobuf.c
++++ b/common/iobuf.c
+@@ -2552,7 +2552,7 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
+      NUL character in the buffer.  This requires at least 2 bytes.  We
+      don't complicate the code by handling the stupid corner case, but
+      simply assert that it can't happen.  */
+-  assert (length >= 2 || maxlen >= 2);
++  assert (!buffer || length >= 2 || maxlen >= 2);
+ 
+   if (!buffer || length <= 1)
+     /* must allocate a new buffer */
diff -Nru gnupg2-2.1.18/debian/patches/0059-gpg-Handle-critical-marked-Reason-for-Revocation.patch gnupg2-2.1.18/debian/patches/0059-gpg-Handle-critical-marked-Reason-for-Revocation.patch
--- gnupg2-2.1.18/debian/patches/0059-gpg-Handle-critical-marked-Reason-for-Revocation.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0059-gpg-Handle-critical-marked-Reason-for-Revocation.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,31 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Mon, 3 Apr 2017 08:51:52 +0200
+Subject: gpg: Handle critical marked 'Reason for Revocation'.
+
+* g10/parse-packet.c (can_handle_critical): Add
+SIGSUBPKT_REVOC_REASON.
+--
+
+Some software seems to mark that subpacket as criticial.  Although gpg
+has no special treatment for a revocation reasons (except for
+--list-packets) we can accept a criticial marked anyway.  There are no
+mandatary rules specified on how to handle a revocation reason.
+
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 3f6d949011f485613bb4bd3e06a2643be79cce40)
+---
+ g10/parse-packet.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/g10/parse-packet.c b/g10/parse-packet.c
+index 7f44ce5..bbb784a 100644
+--- a/g10/parse-packet.c
++++ b/g10/parse-packet.c
+@@ -1572,6 +1572,7 @@ can_handle_critical (const byte * buffer, size_t n, int type)
+       /* Is it enough to show the policy or keyserver? */
+     case SIGSUBPKT_POLICY:
+     case SIGSUBPKT_PREF_KS:
++    case SIGSUBPKT_REVOC_REASON: /* At least we know about it.  */
+       return 1;
+ 
+     default:
diff -Nru gnupg2-2.1.18/debian/patches/0060-dirmngr-Do-not-assume-that-etc-hosts-exists.patch gnupg2-2.1.18/debian/patches/0060-dirmngr-Do-not-assume-that-etc-hosts-exists.patch
--- gnupg2-2.1.18/debian/patches/0060-dirmngr-Do-not-assume-that-etc-hosts-exists.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0060-dirmngr-Do-not-assume-that-etc-hosts-exists.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,61 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Mon, 3 Apr 2017 19:10:50 +0200
+Subject: dirmngr: Do not assume that /etc/hosts exists.
+
+* dirmngr/dns-stuff.c (libdns_init): Do not bail out.
+--
+
+A standard Windows installation does not have a hosts file and thus we
+can't bail out here.  We should also not bail out on a Unix system
+because /etc/hosts is just one method in  nsswitch.conf.
+
+Fixes-commit: 88f1505f0613894d5544290a170119eb538921e5
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 5d873f288e86edfb684f4dd57ac36466b06494a4)
+---
+ dirmngr/dns-stuff.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c
+index c79a9c7..c2d5488 100644
+--- a/dirmngr/dns-stuff.c
++++ b/dirmngr/dns-stuff.c
+@@ -538,10 +538,9 @@ libdns_init (void)
+       goto leave;
+     }
+ 
+-
+   {
+ #if HAVE_W32_SYSTEM
+-    char *hosts_path = xtryasprintf ("%s\System32\drivers\etc\hosts",
++    char *hosts_path = xtryasprintf ("%s\\System32\\drivers\\etc\\hosts",
+                                      getenv ("SystemRoot"));
+     if (! hosts_path)
+       {
+@@ -551,15 +550,24 @@ libdns_init (void)
+ 
+     derr = dns_hosts_loadpath (ld.hosts, hosts_path);
+     xfree (hosts_path);
++    if (derr)
++      {
++        err = libdns_error_to_gpg_error (derr);
++        /* Most Windows systems don't have a hosts files.  So do not
++         * report in this case.  */
++        if (gpg_err_code (err) != GPG_ERR_ENOENT)
++          log_error ("failed to load hosts file: %s\n", gpg_strerror (err));
++        err = 0; /* Do not bail out.  */
++      }
+ #else
+     derr = dns_hosts_loadpath (ld.hosts, "/etc/hosts");
+-#endif
+     if (derr)
+       {
+         err = libdns_error_to_gpg_error (derr);
+         log_error ("failed to load hosts file: %s\n", gpg_strerror (err));
+-        goto leave;
++        err = 0; /* Do not bail out - having no /etc/hosts is legal.  */
+       }
++#endif
+   }
+ 
+   /* dns_hints_local for stub mode, dns_hints_root for recursive.  */
diff -Nru gnupg2-2.1.18/debian/patches/0061-dirmngr-Always-print-a-warning-for-a-missing-etc-hos.patch gnupg2-2.1.18/debian/patches/0061-dirmngr-Always-print-a-warning-for-a-missing-etc-hos.patch
--- gnupg2-2.1.18/debian/patches/0061-dirmngr-Always-print-a-warning-for-a-missing-etc-hos.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0061-dirmngr-Always-print-a-warning-for-a-missing-etc-hos.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,49 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Mon, 3 Apr 2017 20:20:27 +0200
+Subject: dirmngr: Always print a warning for a missing /etc/hosts.
+
+* dirmngr/dns-stuff.c (libdns_init): No Windows specific handling of a
+missing /etc/hosts.
+--
+
+My last comment on this was flawed.  Windows seems to always have its
+version of /etc/hosts.  Only the en passant fixed bad escaping led me
+assume that this was the case.  Thanks to Andre for complaining about
+my comment remark.
+
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 35c843c815306f36d1efbc52f5e2f6bac3f67aec)
+---
+ dirmngr/dns-stuff.c | 11 +----------
+ 1 file changed, 1 insertion(+), 10 deletions(-)
+
+diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c
+index c2d5488..150237e 100644
+--- a/dirmngr/dns-stuff.c
++++ b/dirmngr/dns-stuff.c
+@@ -550,24 +550,15 @@ libdns_init (void)
+ 
+     derr = dns_hosts_loadpath (ld.hosts, hosts_path);
+     xfree (hosts_path);
+-    if (derr)
+-      {
+-        err = libdns_error_to_gpg_error (derr);
+-        /* Most Windows systems don't have a hosts files.  So do not
+-         * report in this case.  */
+-        if (gpg_err_code (err) != GPG_ERR_ENOENT)
+-          log_error ("failed to load hosts file: %s\n", gpg_strerror (err));
+-        err = 0; /* Do not bail out.  */
+-      }
+ #else
+     derr = dns_hosts_loadpath (ld.hosts, "/etc/hosts");
++#endif
+     if (derr)
+       {
+         err = libdns_error_to_gpg_error (derr);
+         log_error ("failed to load hosts file: %s\n", gpg_strerror (err));
+         err = 0; /* Do not bail out - having no /etc/hosts is legal.  */
+       }
+-#endif
+   }
+ 
+   /* dns_hints_local for stub mode, dns_hints_root for recursive.  */
diff -Nru gnupg2-2.1.18/debian/patches/0062-dirmngr-Handle-EIO-which-is-sometimes-returned-by-co.patch gnupg2-2.1.18/debian/patches/0062-dirmngr-Handle-EIO-which-is-sometimes-returned-by-co.patch
--- gnupg2-2.1.18/debian/patches/0062-dirmngr-Handle-EIO-which-is-sometimes-returned-by-co.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0062-dirmngr-Handle-EIO-which-is-sometimes-returned-by-co.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,26 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Mon, 3 Apr 2017 20:23:18 +0200
+Subject: dirmngr: Handle EIO which is sometimes returned by cookie functions.
+
+* dirmngr/ks-engine-hkp.c (handle_send_request_error): Handle EIO.
+--
+
+Suggested-by: Andre Heinecke
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit cc32ddbcba8c53d3e2cad952d72f62dc73911042)
+---
+ dirmngr/ks-engine-hkp.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
+index 32db4bc..66350a7 100644
+--- a/dirmngr/ks-engine-hkp.c
++++ b/dirmngr/ks-engine-hkp.c
+@@ -1245,6 +1245,7 @@ handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
+     case GPG_ERR_ENETDOWN:
+     case GPG_ERR_UNKNOWN_HOST:
+     case GPG_ERR_NETWORK:
++    case GPG_ERR_EIO:  /* Sometimes used by estream cookie functions.  */
+       if (mark_host_dead (request) && *tries_left)
+         retry = 1;
+       break;
diff -Nru gnupg2-2.1.18/debian/patches/0063-dirmngr-New-option-disable-ipv6.patch gnupg2-2.1.18/debian/patches/0063-dirmngr-New-option-disable-ipv6.patch
--- gnupg2-2.1.18/debian/patches/0063-dirmngr-New-option-disable-ipv6.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0063-dirmngr-New-option-disable-ipv6.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,241 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Mon, 3 Apr 2017 20:56:12 +0200
+Subject: dirmngr: New option --disable-ipv6
+
+* dirmngr/dirmngr.h (struct opt): Add field 'disable_ipv6'.
+* dirmngr/dirmngr.c (oDisableIPv6): New const.
+(opts): New option --disable-ipv6.
+(parse_rereadable_options): Set that option.
+* dirmngr/dns-stuff.c (opt_disable_ipv6): New var.
+(set_dns_disable_ipv6): New.
+(resolve_name_standard): Make use of it.
+* dirmngr/ks-engine-finger.c (ks_finger_fetch): Take care of
+OPT.DISABLE_IPV6.
+* dirmngr/ks-engine-hkp.c (map_host): Ditto.
+(send_request): 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 3533b854408fa93734742b2ee12b62aa0d55ff28)
+---
+ dirmngr/crlfetch.c         |  1 +
+ dirmngr/dirmngr.c          |  4 ++++
+ dirmngr/dirmngr.h          |  3 ++-
+ dirmngr/dns-stuff.c        | 15 +++++++++++++++
+ dirmngr/dns-stuff.h        |  4 ++++
+ dirmngr/ks-engine-finger.c |  3 ++-
+ dirmngr/ks-engine-hkp.c    |  7 +++++--
+ dirmngr/ks-engine-http.c   |  3 ++-
+ dirmngr/ocsp.c             |  3 ++-
+ doc/dirmngr.texi           |  5 +++--
+ 10 files changed, 40 insertions(+), 8 deletions(-)
+
+diff --git a/dirmngr/crlfetch.c b/dirmngr/crlfetch.c
+index 337fe6e..2700cf9 100644
+--- a/dirmngr/crlfetch.c
++++ b/dirmngr/crlfetch.c
+@@ -200,6 +200,7 @@ crl_fetch (ctrl_t ctrl, const char *url, ksba_reader_t *reader)
+                                    |(DBG_LOOKUP? HTTP_FLAG_LOG_RESP:0)
+                                    |(dirmngr_use_tor()? HTTP_FLAG_FORCE_TOR:0)
+                                    |(opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4:0)
++                                   |(opt.disable_ipv6? HTTP_FLAG_IGNORE_IPv6:0)
+                                    ),
+                                   ctrl->http_proxy, NULL, NULL, NULL);
+ 
+diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
+index 43e9cbd..31d3ca2 100644
+--- a/dirmngr/dirmngr.c
++++ b/dirmngr/dirmngr.c
+@@ -112,6 +112,7 @@ enum cmd_and_opt_values {
+   oDisableHTTP,
+   oDisableLDAP,
+   oDisableIPv4,
++  oDisableIPv6,
+   oIgnoreLDAPDP,
+   oIgnoreHTTPDP,
+   oIgnoreOCSPSvcUrl,
+@@ -228,6 +229,7 @@ static ARGPARSE_OPTS opts[] = {
+   ARGPARSE_s_n (oNoUseTor, "no-use-tor", "@"),
+ 
+   ARGPARSE_s_n (oDisableIPv4, "disable-ipv4", "@"),
++  ARGPARSE_s_n (oDisableIPv6, "disable-ipv6", "@"),
+ 
+   ARGPARSE_s_s (oSocketName, "socket-name", "@"),  /* Only for debugging.  */
+ 
+@@ -624,6 +626,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 oDisableIPv6: opt.disable_ipv6 = 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;
+@@ -690,6 +693,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);
++  set_dns_disable_ipv6 (opt.disable_ipv6);
+ 
+   return 1; /* Handled. */
+ }
+diff --git a/dirmngr/dirmngr.h b/dirmngr/dirmngr.h
+index 6a4fd00..4cc2be0 100644
+--- a/dirmngr/dirmngr.h
++++ b/dirmngr/dirmngr.h
+@@ -97,7 +97,8 @@ 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 disable_ipv4;       /* Do not use legacy IP addresses.  */
++  int disable_ipv6;       /* Do not use standard 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 150237e..ed77742 100644
+--- a/dirmngr/dns-stuff.c
++++ b/dirmngr/dns-stuff.c
+@@ -123,6 +123,10 @@ static int opt_timeout;
+  * returned A records.  */
+ static int opt_disable_ipv4;
+ 
++/* The flag to disable IPv6 access - right now this only skips
++ * returned AAAA records.  */
++static int opt_disable_ipv6;
++
+ /* If set force the use of the standard resolver.  */
+ static int standard_resolver;
+ 
+@@ -248,6 +252,15 @@ set_dns_disable_ipv4 (int yes)
+ }
+ 
+ 
++/* Set the Disable-IPv6 flag so that the name resolver does not return
++ * AAAA addresses.  */
++void
++set_dns_disable_ipv6 (int yes)
++{
++  opt_disable_ipv6 = !!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
+@@ -934,6 +947,8 @@ resolve_name_standard (const char *name, unsigned short port,
+         continue;
+       if (opt_disable_ipv4 && ai->ai_family == AF_INET)
+         continue;
++      if (opt_disable_ipv6 && ai->ai_family == AF_INET6)
++        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 9b8303c..71605b7 100644
+--- a/dirmngr/dns-stuff.h
++++ b/dirmngr/dns-stuff.h
+@@ -99,6 +99,10 @@ void set_dns_verbose (int verbose, int debug);
+  * A addresses.  */
+ void set_dns_disable_ipv4 (int yes);
+ 
++/* Set the Disable-IPv6 flag so that the name resolver does not return
++ * AAAA addresses.  */
++void set_dns_disable_ipv6 (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 811b72d..8a21c9f 100644
+--- a/dirmngr/ks-engine-finger.c
++++ b/dirmngr/ks-engine-finger.c
+@@ -84,7 +84,8 @@ ks_finger_fetch (ctrl_t ctrl, parsed_uri_t uri, estream_t *r_fp)
+ 
+   err = http_raw_connect (&http, server, 79,
+                           ((dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR : 0)
+-                           | (opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)),
++                           | (opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)
++                           | (opt.disable_ipv6? HTTP_FLAG_IGNORE_IPv6 : 0)),
+                           NULL);
+   if (err)
+     {
+diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
+index 66350a7..7c91b6a 100644
+--- a/dirmngr/ks-engine-hkp.c
++++ b/dirmngr/ks-engine-hkp.c
+@@ -568,6 +568,8 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
+                 continue;
+               if (opt.disable_ipv4 && ai->family == AF_INET)
+                 continue;
++              if (opt.disable_ipv6 && ai->family == AF_INET6)
++                continue;
+               dirmngr_tick (ctrl);
+ 
+               add_host (name, is_pool, ai, 0, reftbl, reftblsize, &refidx);
+@@ -649,7 +651,7 @@ 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
++              if ((!opt.disable_ipv6 && ai->family == AF_INET6)
+                   || (!opt.disable_ipv4 && ai->family == AF_INET))
+                 {
+                   err = resolve_dns_addr (ai->addr, ai->addrlen, 0, &host);
+@@ -1102,7 +1104,8 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
+                    (httpflags
+                     |(opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
+                     |(dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR:0)
+-                    |(opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)),
++                    |(opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)
++                    |(opt.disable_ipv6? HTTP_FLAG_IGNORE_IPv6 : 0)),
+                    ctrl->http_proxy,
+                    session,
+                    NULL,
+diff --git a/dirmngr/ks-engine-http.c b/dirmngr/ks-engine-http.c
+index 69642ff..6de0616 100644
+--- a/dirmngr/ks-engine-http.c
++++ b/dirmngr/ks-engine-http.c
+@@ -89,7 +89,8 @@ ks_http_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp)
+                    /* fixme: AUTH */ NULL,
+                    ((opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
+                     | (dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR:0)
+-                    | (opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)),
++                    | (opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)
++                    | (opt.disable_ipv6? HTTP_FLAG_IGNORE_IPv6 : 0)),
+                    ctrl->http_proxy,
+                    session,
+                    NULL,
+diff --git a/dirmngr/ocsp.c b/dirmngr/ocsp.c
+index aff8e32..22391c3 100644
+--- a/dirmngr/ocsp.c
++++ b/dirmngr/ocsp.c
+@@ -175,7 +175,8 @@ do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md,
+   err = http_open (&http, HTTP_REQ_POST, url, NULL, NULL,
+                    ((opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
+                     | (dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR:0)
+-                    | (opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)),
++                    | (opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)
++                    | (opt.disable_ipv6? HTTP_FLAG_IGNORE_IPv6 : 0)),
+                    ctrl->http_proxy, NULL, NULL, NULL);
+   if (err)
+     {
+diff --git a/doc/dirmngr.texi b/doc/dirmngr.texi
+index b00c2d3..9a7238f 100644
+--- a/doc/dirmngr.texi
++++ b/doc/dirmngr.texi
+@@ -313,9 +313,10 @@ a numerical IP address must be given (IPv6 or IPv4) and that no error
+ checking is done for @var{ipaddr}.
+ 
+ @item --disable-ipv4
++ at item --disable-ipv6
+ @opindex disable-ipv4
+-Disable the use of all IPv4 addresses.  This option is mainly useful
+-for debugging.
++ at opindex disable-ipv6
++Disable the use of all IPv4 or IPv6 addresses.
+ 
+ @item --disable-ldap
+ @opindex disable-ldap
diff -Nru gnupg2-2.1.18/debian/patches/0064-agent-Serialize-access-to-passphrase-cache.patch gnupg2-2.1.18/debian/patches/0064-agent-Serialize-access-to-passphrase-cache.patch
--- gnupg2-2.1.18/debian/patches/0064-agent-Serialize-access-to-passphrase-cache.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0064-agent-Serialize-access-to-passphrase-cache.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,220 @@
+From: NIIBE Yutaka <gniibe at fsij.org>
+Date: Fri, 7 Apr 2017 08:39:26 +0900
+Subject: agent: Serialize access to passphrase cache.
+
+* agent/cache.c (encryption_lock): Remove.
+(cache_lock): New.  Now, we have coarse grain lock to serialize
+entire cache access.
+(initialize_module_cache): Use CACHE_LOCK.
+(init_encryption, new_data): Remove ENCRYPTION_LOCK.
+(agent_flush_cache, agent_put_cache, agent_get_cache): Lock the cache.
+
+--
+
+GnuPG-bug-id: 3027
+Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>
+(cherry picked from commit ebe12be034f052cdec871f0d8ad1bfab85d7b943)
+---
+ agent/cache.c | 73 ++++++++++++++++++++++++++++++-----------------------------
+ 1 file changed, 37 insertions(+), 36 deletions(-)
+
+diff --git a/agent/cache.c b/agent/cache.c
+index 2483682..fead737 100644
+--- a/agent/cache.c
++++ b/agent/cache.c
+@@ -31,9 +31,8 @@
+ /* The size of the encryption key in bytes.  */
+ #define ENCRYPTION_KEYSIZE (128/8)
+ 
+-/* A mutex used to protect the encryption.  This is required because
+-   we use one context to do all encryption and decryption.  */
+-static npth_mutex_t encryption_lock;
++/* A mutex used to serialize access to the cache.  */
++static npth_mutex_t cache_lock;
+ /* The encryption context.  This is the only place where the
+    encryption key for all cached entries is available.  It would be nice
+    to keep this (or just the key) in some hardware device, for example
+@@ -76,7 +75,7 @@ initialize_module_cache (void)
+ {
+   int err;
+ 
+-  err = npth_mutex_init (&encryption_lock, NULL);
++  err = npth_mutex_init (&cache_lock, NULL);
+ 
+   if (err)
+     log_fatal ("error initializing cache module: %s\n", strerror (err));
+@@ -102,15 +101,10 @@ init_encryption (void)
+ {
+   gpg_error_t err;
+   void *key;
+-  int res;
+ 
+   if (encryption_handle)
+     return 0; /* Shortcut - Already initialized.  */
+ 
+-  res = npth_mutex_lock (&encryption_lock);
+-  if (res)
+-    log_fatal ("failed to acquire cache encryption mutex: %s\n", strerror (res));
+-
+   err = gcry_cipher_open (&encryption_handle, GCRY_CIPHER_AES128,
+                           GCRY_CIPHER_MODE_AESWRAP, GCRY_CIPHER_SECURE);
+   if (!err)
+@@ -133,10 +127,6 @@ init_encryption (void)
+     log_error ("error initializing cache encryption context: %s\n",
+                gpg_strerror (err));
+ 
+-  res = npth_mutex_unlock (&encryption_lock);
+-  if (res)
+-    log_fatal ("failed to release cache encryption mutex: %s\n", strerror (res));
+-
+   return err? gpg_error (GPG_ERR_NOT_INITIALIZED) : 0;
+ }
+ 
+@@ -155,7 +145,6 @@ new_data (const char *string, struct secret_data_s **r_data)
+   struct secret_data_s *d, *d_enc;
+   size_t length;
+   int total;
+-  int res;
+ 
+   *r_data = NULL;
+ 
+@@ -186,17 +175,9 @@ new_data (const char *string, struct secret_data_s **r_data)
+     }
+ 
+   d_enc->totallen = total;
+-  res = npth_mutex_lock (&encryption_lock);
+-  if (res)
+-    log_fatal ("failed to acquire cache encryption mutex: %s\n",
+-               strerror (res));
+-
+   err = gcry_cipher_encrypt (encryption_handle, d_enc->data, total,
+                              d->data, total - 8);
+   xfree (d);
+-  res = npth_mutex_unlock (&encryption_lock);
+-  if (res)
+-    log_fatal ("failed to release cache encryption mutex: %s\n", strerror (res));
+   if (err)
+     {
+       xfree (d_enc);
+@@ -281,10 +262,15 @@ void
+ agent_flush_cache (void)
+ {
+   ITEM r;
++  int res;
+ 
+   if (DBG_CACHE)
+     log_debug ("agent_flush_cache\n");
+ 
++  res = npth_mutex_lock (&cache_lock);
++  if (res)
++    log_fatal ("failed to acquire cache mutex: %s\n", strerror (res));
++
+   for (r=thecache; r; r = r->next)
+     {
+       if (r->pw)
+@@ -296,6 +282,10 @@ agent_flush_cache (void)
+           r->accessed = 0;
+         }
+     }
++
++  res = npth_mutex_unlock (&cache_lock);
++  if (res)
++    log_fatal ("failed to release cache mutex: %s\n", strerror (res));
+ }
+ 
+ 
+@@ -321,6 +311,11 @@ agent_put_cache (const char *key, cache_mode_t cache_mode,
+ {
+   gpg_error_t err = 0;
+   ITEM r;
++  int res;
++
++  res = npth_mutex_lock (&cache_lock);
++  if (res)
++    log_fatal ("failed to acquire cache mutex: %s\n", strerror (res));
+ 
+   if (DBG_CACHE)
+     log_debug ("agent_put_cache '%s' (mode %d) requested ttl=%d\n",
+@@ -336,7 +331,7 @@ agent_put_cache (const char *key, cache_mode_t cache_mode,
+         }
+     }
+   if ((!ttl && data) || cache_mode == CACHE_MODE_IGNORE)
+-    return 0;
++    goto out;
+ 
+   for (r=thecache; r; r = r->next)
+     {
+@@ -386,6 +381,12 @@ agent_put_cache (const char *key, cache_mode_t cache_mode,
+       if (err)
+         log_error ("error inserting cache item: %s\n", gpg_strerror (err));
+     }
++
++ out:
++  res = npth_mutex_unlock (&cache_lock);
++  if (res)
++    log_fatal ("failed to release cache mutex: %s\n", strerror (res));
++
+   return err;
+ }
+ 
+@@ -405,15 +406,18 @@ agent_get_cache (const char *key, cache_mode_t cache_mode)
+   if (cache_mode == CACHE_MODE_IGNORE)
+     return NULL;
+ 
++  res = npth_mutex_lock (&cache_lock);
++  if (res)
++    log_fatal ("failed to acquire cache mutex: %s\n", strerror (res));
++
+   if (!key)
+     {
+       key = last_stored_cache_key;
+       if (!key)
+-        return NULL;
++        goto out;
+       last_stored = 1;
+     }
+ 
+-
+   if (DBG_CACHE)
+     log_debug ("agent_get_cache '%s' (mode %d)%s ...\n",
+                key, cache_mode,
+@@ -440,17 +444,9 @@ agent_get_cache (const char *key, cache_mode_t cache_mode)
+             err = gpg_error_from_syserror ();
+           else
+             {
+-              res = npth_mutex_lock (&encryption_lock);
+-              if (res)
+-                log_fatal ("failed to acquire cache encryption mutex: %s\n",
+-			   strerror (res));
+               err = gcry_cipher_decrypt (encryption_handle,
+                                          value, r->pw->totallen - 8,
+                                          r->pw->data, r->pw->totallen);
+-              res = npth_mutex_unlock (&encryption_lock);
+-              if (res)
+-                log_fatal ("failed to release cache encryption mutex: %s\n",
+-			   strerror (res));
+             }
+           if (err)
+             {
+@@ -459,13 +455,18 @@ agent_get_cache (const char *key, cache_mode_t cache_mode)
+               log_error ("retrieving cache entry '%s' failed: %s\n",
+                          key, gpg_strerror (err));
+             }
+-          return value;
++          break;
+         }
+     }
+-  if (DBG_CACHE)
++  if (DBG_CACHE && value == NULL)
+     log_debug ("... miss\n");
+ 
+-  return NULL;
++ out:
++  res = npth_mutex_unlock (&cache_lock);
++  if (res)
++    log_fatal ("failed to release cache mutex: %s\n", strerror (res));
++
++  return value;
+ }
+ 
+ 
diff -Nru gnupg2-2.1.18/debian/patches/0065-gpg-Fix-printing-of-offline-taken-subkey.patch gnupg2-2.1.18/debian/patches/0065-gpg-Fix-printing-of-offline-taken-subkey.patch
--- gnupg2-2.1.18/debian/patches/0065-gpg-Fix-printing-of-offline-taken-subkey.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0065-gpg-Fix-printing-of-offline-taken-subkey.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,27 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Fri, 7 Apr 2017 10:11:07 +0200
+Subject: gpg: Fix printing of offline taken subkey.
+
+* g10/keylist.c (list_keyblock_print): Set SECRET to 2 and not 0x32.
+--
+
+Reported-by: Danielle McLean <dani at 00dani.me>
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 547bc01d57528ecc27b3b5e16797967a7f88fecf)
+---
+ g10/keylist.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/g10/keylist.c b/g10/keylist.c
+index 4078053..1998ee9 100644
+--- a/g10/keylist.c
++++ b/g10/keylist.c
+@@ -1017,7 +1017,7 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
+               if (!agent_get_keyinfo (NULL, hexgrip, &serialno, NULL))
+                 secret = serialno? 3 : 1;
+               else
+-                secret = '2';  /* Key not found.  */
++                secret = 2;  /* Key not found.  */
+             }
+ 
+           /* Print the "sub" line.  */
diff -Nru gnupg2-2.1.18/debian/patches/0066-doc-Explain-the-in-a-key-listing.patch gnupg2-2.1.18/debian/patches/0066-doc-Explain-the-in-a-key-listing.patch
--- gnupg2-2.1.18/debian/patches/0066-doc-Explain-the-in-a-key-listing.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0066-doc-Explain-the-in-a-key-listing.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,34 @@
+From: Werner Koch <wk at gnupg.org>
+Date: Fri, 7 Apr 2017 10:26:55 +0200
+Subject: doc: Explain the '>' in a key listing.
+
+--
+
+Signed-off-by: Werner Koch <wk at gnupg.org>
+(cherry picked from commit 9c9fde1495be4accf4526a2626110876fd9d788d)
+---
+ doc/gpg.texi | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/doc/gpg.texi b/doc/gpg.texi
+index d658737..c591049 100644
+--- a/doc/gpg.texi
++++ b/doc/gpg.texi
+@@ -301,10 +301,13 @@ and other programs.
+ @itemx -K
+ @opindex list-secret-keys
+ List the specified secret keys.  If no keys are specified, then all
+-known secret keys are listed.  A @code{#} after the letters @code{sec}
+-means that the secret key is not usable (for example, if it was
+-exported using @option{--export-secret-subkeys}).  See also
+- at option{--list-keys}.
++known secret keys are listed.  A @code{#} after the intial tags
++ at code{sec} or @code{ssb} means that the secret key or subkey is
++currently not usable.  We also say that this key has been taken
++offline (for example, a primary key can be taken offline by exported
++the key using the command @option{--export-secret-subkeys}).  A
++ at code{>} after these tags indicate that the key is stored on a
++smartcard.  See also @option{--list-keys}.
+ 
+ @item --list-signatures
+ @opindex list-signatures
diff -Nru gnupg2-2.1.18/debian/patches/0067-dirmngr-Fix-possible-null-reference.patch gnupg2-2.1.18/debian/patches/0067-dirmngr-Fix-possible-null-reference.patch
--- gnupg2-2.1.18/debian/patches/0067-dirmngr-Fix-possible-null-reference.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0067-dirmngr-Fix-possible-null-reference.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,28 @@
+From: NIIBE Yutaka <gniibe at fsij.org>
+Date: Wed, 12 Apr 2017 15:58:11 +0900
+Subject: dirmngr: Fix possible null reference.
+
+* dirmngr/dns.c (dns_error_t dns_trace_fput): Check NULL.
+
+Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>
+(cherry picked from commit 7ae1857c90ab43ad9e31f0fb6dbd37f25cc37278)
+---
+ dirmngr/dns.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/dirmngr/dns.c b/dirmngr/dns.c
+index 869e7ed..ebfd4c3 100644
+--- a/dirmngr/dns.c
++++ b/dirmngr/dns.c
+@@ -4594,8 +4594,9 @@ dns_error_t dns_trace_fput(const struct dns_trace_event *te, const void *data, s
+ 
+ 	if (fwrite(&tmp, 1, headsize, fp) < headsize)
+ 		return errno;
+-	if (fwrite(data, 1, datasize, fp) < datasize)
+-		return errno;
++	if (data)
++		if (fwrite(data, 1, datasize, fp) < datasize)
++			return errno;
+ 	if (fflush(fp))
+ 		return errno;
+ 
diff -Nru gnupg2-2.1.18/debian/patches/0068-tools-Fix-condition-for-gpg-connect-agent.patch gnupg2-2.1.18/debian/patches/0068-tools-Fix-condition-for-gpg-connect-agent.patch
--- gnupg2-2.1.18/debian/patches/0068-tools-Fix-condition-for-gpg-connect-agent.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0068-tools-Fix-condition-for-gpg-connect-agent.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,30 @@
+From: NIIBE Yutaka <gniibe at fsij.org>
+Date: Wed, 12 Apr 2017 16:01:16 +0900
+Subject: tools: Fix condition for gpg-connect-agent.
+
+* tools/gpg-connect-agent.c (start_agent): Add paren.
+
+--
+
+The intention is comparing the error code depending opt.use_dirmngr.
+Considering C Operator Precedence, we should have paren here.
+
+Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>
+(cherry picked from commit f52f6af834cc488d11612e349e4af023d69a45f4)
+---
+ tools/gpg-connect-agent.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c
+index a5413cf..5af1465 100644
+--- a/tools/gpg-connect-agent.c
++++ b/tools/gpg-connect-agent.c
+@@ -2237,7 +2237,7 @@ start_agent (void)
+     {
+       if (!opt.autostart
+           && (gpg_err_code (err)
+-              == opt.use_dirmngr? GPG_ERR_NO_DIRMNGR : GPG_ERR_NO_AGENT))
++              == (opt.use_dirmngr? GPG_ERR_NO_DIRMNGR : GPG_ERR_NO_AGENT)))
+         {
+           /* In the no-autostart case we don't make gpg-connect-agent
+              fail on a missing server.  */
diff -Nru gnupg2-2.1.18/debian/patches/0069-dirmngr-Fix-alignment-of-ADDR.patch gnupg2-2.1.18/debian/patches/0069-dirmngr-Fix-alignment-of-ADDR.patch
--- gnupg2-2.1.18/debian/patches/0069-dirmngr-Fix-alignment-of-ADDR.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0069-dirmngr-Fix-alignment-of-ADDR.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,155 @@
+From: NIIBE Yutaka <gniibe at fsij.org>
+Date: Thu, 13 Apr 2017 14:33:33 +0900
+Subject: dirmngr: Fix alignment of ADDR.
+
+* dirmngr/dns-stuff.h (dns_addrinfo_s): Use struct sockaddr_storage
+for size and alignment.
+* dirmngr/dns-stuff.c (resolve_name_libdns): Follow the change.
+(resolve_dns_name): Use struct sockaddr_storage.
+(resolve_addr_standard, resolve_dns_addr): Likewise.
+(resolve_dns_addr): Likewise.
+
+Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>
+(cherry picked from commit 892b33bb2c57785927ea6652091191da2deed464)
+---
+ dirmngr/dns-stuff.c | 31 +++++++++++++++++--------------
+ dirmngr/dns-stuff.h |  4 ++--
+ 2 files changed, 19 insertions(+), 16 deletions(-)
+
+diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c
+index ed77742..c63d958 100644
+--- a/dirmngr/dns-stuff.c
++++ b/dirmngr/dns-stuff.c
+@@ -827,7 +827,7 @@ resolve_name_libdns (const char *name, unsigned short port,
+             (*r_canonname)[strlen (*r_canonname)-1] = 0;
+         }
+ 
+-      dai = xtrymalloc (sizeof *dai + ent->ai_addrlen -1);
++      dai = xtrymalloc (sizeof *dai);
+       if (dai == NULL)
+         {
+           err = gpg_error_from_syserror ();
+@@ -950,7 +950,7 @@ resolve_name_standard (const char *name, unsigned short port,
+       if (opt_disable_ipv6 && ai->ai_family == AF_INET6)
+         continue;
+ 
+-      dai = xtrymalloc (sizeof *dai + ai->ai_addrlen - 1);
++      dai = xtrymalloc (sizeof *dai);
+       dai->family = ai->ai_family;
+       dai->socktype = ai->ai_socktype;
+       dai->protocol = ai->ai_protocol;
+@@ -1018,7 +1018,7 @@ resolve_dns_name (const char *name, unsigned short port,
+ #ifdef USE_LIBDNS
+ /* Resolve an address using libdns.  */
+ static gpg_error_t
+-resolve_addr_libdns (const struct sockaddr *addr, int addrlen,
++resolve_addr_libdns (const struct sockaddr_storage *addr, int addrlen,
+                      unsigned int flags, char **r_name)
+ {
+   gpg_error_t err;
+@@ -1032,13 +1032,13 @@ resolve_addr_libdns (const struct sockaddr *addr, int addrlen,
+ 
+   /* First we turn ADDR into a DNS name (with ".arpa" suffix).  */
+   err = 0;
+-  if (addr->sa_family == AF_INET6)
++  if (addr->ss_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)
++  else if (addr->ss_family == AF_INET)
+     {
+       const struct sockaddr_in *a4 = (const struct sockaddr_in *)addr;
+       if (!dns_a_arpa (host, sizeof host, (void*)&a4->sin_addr))
+@@ -1126,18 +1126,19 @@ resolve_addr_libdns (const struct sockaddr *addr, int addrlen,
+       buflen = sizeof ptr.host;
+ 
+       p = buffer;
+-      if (addr->sa_family == AF_INET6 && (flags & DNS_WITHBRACKET))
++      if (addr->ss_family == AF_INET6 && (flags & DNS_WITHBRACKET))
+         {
+           *p++ = '[';
+           buflen -= 2;
+         }
+-      ec = getnameinfo (addr, addrlen, p, buflen, NULL, 0, NI_NUMERICHOST);
++      ec = getnameinfo ((const struct sockaddr *)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))
++      if (addr->ss_family == AF_INET6 && (flags & DNS_WITHBRACKET))
+         strcat (buffer, "]");
+     }
+ 
+@@ -1151,7 +1152,7 @@ resolve_addr_libdns (const struct sockaddr *addr, int addrlen,
+ 
+ /* Resolve an address using the standard system function.  */
+ static gpg_error_t
+-resolve_addr_standard (const struct sockaddr *addr, int addrlen,
++resolve_addr_standard (const struct sockaddr_storage *addr, int addrlen,
+                        unsigned int flags, char **r_name)
+ {
+   gpg_error_t err;
+@@ -1169,20 +1170,22 @@ resolve_addr_standard (const struct sockaddr *addr, int addrlen,
+   if ((flags & DNS_NUMERICHOST) || tor_mode)
+     ec = EAI_NONAME;
+   else
+-    ec = getnameinfo (addr, addrlen, buffer, buflen, NULL, 0, NI_NAMEREQD);
++    ec = getnameinfo ((const struct sockaddr *)addr,
++                      addrlen, buffer, buflen, NULL, 0, NI_NAMEREQD);
+ 
+   if (!ec && *buffer == '[')
+     ec = EAI_FAIL;  /* A name may never start with a bracket.  */
+   else if (ec == EAI_NONAME)
+     {
+       p = buffer;
+-      if (addr->sa_family == AF_INET6 && (flags & DNS_WITHBRACKET))
++      if (addr->ss_family == AF_INET6 && (flags & DNS_WITHBRACKET))
+         {
+           *p++ = '[';
+           buflen -= 2;
+         }
+-      ec = getnameinfo (addr, addrlen, p, buflen, NULL, 0, NI_NUMERICHOST);
+-      if (!ec && addr->sa_family == AF_INET6 && (flags & DNS_WITHBRACKET))
++      ec = getnameinfo ((const struct sockaddr *)addr,
++                        addrlen, p, buflen, NULL, 0, NI_NUMERICHOST);
++      if (!ec && addr->ss_family == AF_INET6 && (flags & DNS_WITHBRACKET))
+         strcat (buffer, "]");
+     }
+ 
+@@ -1211,7 +1214,7 @@ resolve_addr_standard (const struct sockaddr *addr, int addrlen,
+ 
+ /* A wrapper around getnameinfo.  */
+ gpg_error_t
+-resolve_dns_addr (const struct sockaddr *addr, int addrlen,
++resolve_dns_addr (const struct sockaddr_storage *addr, int addrlen,
+                   unsigned int flags, char **r_name)
+ {
+   gpg_error_t err;
+diff --git a/dirmngr/dns-stuff.h b/dirmngr/dns-stuff.h
+index 71605b7..adb0b80 100644
+--- a/dirmngr/dns-stuff.h
++++ b/dirmngr/dns-stuff.h
+@@ -78,7 +78,7 @@ struct dns_addrinfo_s
+   int socktype;
+   int protocol;
+   int addrlen;
+-  struct sockaddr addr[1];
++  struct sockaddr_storage addr[1];
+ };
+ 
+ 
+@@ -142,7 +142,7 @@ gpg_error_t resolve_dns_name (const char *name, unsigned short port,
+                               dns_addrinfo_t *r_dai, char **r_canonname);
+ 
+ /* Function similar to getnameinfo.  */
+-gpg_error_t resolve_dns_addr (const struct sockaddr *addr, int addrlen,
++gpg_error_t resolve_dns_addr (const struct sockaddr_storage *addr, int addrlen,
+                               unsigned int flags, char **r_name);
+ 
+ /* Return true if NAME is a numerical IP address.  */
diff -Nru gnupg2-2.1.18/debian/patches/0070-dirmngr-Fix-http.c-for-sockaddr_storage.patch gnupg2-2.1.18/debian/patches/0070-dirmngr-Fix-http.c-for-sockaddr_storage.patch
--- gnupg2-2.1.18/debian/patches/0070-dirmngr-Fix-http.c-for-sockaddr_storage.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0070-dirmngr-Fix-http.c-for-sockaddr_storage.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,70 @@
+From: NIIBE Yutaka <gniibe at fsij.org>
+Date: Thu, 13 Apr 2017 14:46:57 +0900
+Subject: dirmngr: Fix http.c for sockaddr_storage.
+
+dirmngr/http.c (use_socks): Use sockaddr_storage.
+(my_sock_new_for_addr, connect_server): Likewise.
+
+Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>
+(cherry picked from commit 86dcb03134fd4957d51ebaa06b7991239f9ee56a)
+---
+ dirmngr/http.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/dirmngr/http.c b/dirmngr/http.c
+index c9c16df..674cb3d 100644
+--- a/dirmngr/http.c
++++ b/dirmngr/http.c
+@@ -2415,13 +2415,13 @@ start_server ()
+  * This function is basically a copy of the same internal fucntion in
+  * Libassuan.  */
+ static int
+-use_socks (struct sockaddr *addr)
++use_socks (struct sockaddr_storage *addr)
+ {
+   int mode;
+ 
+   if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
+     return 0;  /* Not in Tor mode.  */
+-  else if (addr->sa_family == AF_INET6)
++  else if (addr->ss_family == AF_INET6)
+     {
+       struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr;
+       const unsigned char *s;
+@@ -2436,7 +2436,7 @@ use_socks (struct sockaddr *addr)
+ 
+       return 0; /* This is the loopback address.  */
+     }
+-  else if (addr->sa_family == AF_INET)
++  else if (addr->ss_family == AF_INET)
+     {
+       struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
+ 
+@@ -2453,7 +2453,7 @@ use_socks (struct sockaddr *addr)
+ /* Wrapper around assuan_sock_new which takes the domain from an
+  * address parameter.  */
+ static assuan_fd_t
+-my_sock_new_for_addr (struct sockaddr *addr, int type, int proto)
++my_sock_new_for_addr (struct sockaddr_storage *addr, int type, int proto)
+ {
+   int domain;
+ 
+@@ -2464,7 +2464,7 @@ my_sock_new_for_addr (struct sockaddr *addr, int type, int proto)
+       domain = AF_INET;
+     }
+   else
+-    domain = addr->sa_family;
++    domain = addr->ss_family;
+ 
+   return assuan_sock_new (domain, type, proto);
+ }
+@@ -2589,7 +2589,8 @@ connect_server (const char *server, unsigned short port,
+             }
+ 
+           anyhostaddr = 1;
+-          if (assuan_sock_connect (sock, ai->addr, ai->addrlen))
++          if (assuan_sock_connect (sock, (struct sockaddr *)ai->addr,
++                                   ai->addrlen))
+             {
+               last_err = gpg_err_make (default_errsource,
+                                        gpg_err_code_from_syserror ());
diff -Nru gnupg2-2.1.18/debian/patches/0071-g10-Fix-import-export-filter-property-match.patch gnupg2-2.1.18/debian/patches/0071-g10-Fix-import-export-filter-property-match.patch
--- gnupg2-2.1.18/debian/patches/0071-g10-Fix-import-export-filter-property-match.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0071-g10-Fix-import-export-filter-property-match.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,25 @@
+From: NIIBE Yutaka <gniibe at fsij.org>
+Date: Mon, 17 Apr 2017 09:08:31 +0900
+Subject: g10: Fix import/export filter property match.
+
+* g10/import.c (impex_filter_getval): Fix to "else if".
+
+Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>
+(cherry picked from commit af5f8ecf51f5e1f33e832d4946d02313b78a0536)
+---
+ g10/import.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/g10/import.c b/g10/import.c
+index 4e6f692..125b994 100644
+--- a/g10/import.c
++++ b/g10/import.c
+@@ -1235,7 +1235,7 @@ impex_filter_getval (void *cookie, const char *propname)
+           snprintf (numbuf, sizeof numbuf, "%d", pk->pubkey_algo);
+           result = numbuf;
+         }
+-      if (!strcmp (propname, "key_created"))
++      else if (!strcmp (propname, "key_created"))
+         {
+           snprintf (numbuf, sizeof numbuf, "%lu", (ulong)pk->timestamp);
+           result = numbuf;
diff -Nru gnupg2-2.1.18/debian/patches/0072-g10-Minor-fixes.patch gnupg2-2.1.18/debian/patches/0072-g10-Minor-fixes.patch
--- gnupg2-2.1.18/debian/patches/0072-g10-Minor-fixes.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0072-g10-Minor-fixes.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,66 @@
+From: NIIBE Yutaka <gniibe at fsij.org>
+Date: Mon, 17 Apr 2017 09:15:13 +0900
+Subject: g10: Minor fixes.
+
+* g10/export.c (cleartext_secret_key_to_openpgp): No initialization.
+(do_export_one_keyblock): Initialize with GPG_ERR_NOT_FOUND.
+* g10/getkey.c (get_best_pubkey_byname): Add non-null check.
+* g10/tofu.c (tofu_set_policy): ERR initialize to 0.
+
+Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>
+(cherry picked from commit 0dec0cc281dfa26db89f8cc5ee002dea5c2b2e81)
+---
+ g10/export.c | 4 ++--
+ g10/getkey.c | 3 ++-
+ g10/tofu.c   | 2 +-
+ 3 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/g10/export.c b/g10/export.c
+index 207f994..ea9ffb4 100644
+--- a/g10/export.c
++++ b/g10/export.c
+@@ -580,7 +580,7 @@ canon_pk_algo (enum gcry_pk_algos algo)
+ static gpg_error_t
+ cleartext_secret_key_to_openpgp (gcry_sexp_t s_key, PKT_public_key *pk)
+ {
+-  gpg_error_t err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
++  gpg_error_t err;
+   gcry_sexp_t top_list;
+   gcry_sexp_t key = NULL;
+   char *key_type = NULL;
+@@ -1524,7 +1524,7 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
+                         KEYDB_SEARCH_DESC *desc, size_t ndesc,
+                         size_t descindex, gcry_cipher_hd_t cipherhd)
+ {
+-  gpg_error_t err;
++  gpg_error_t err = gpg_error (GPG_ERR_NOT_FOUND);
+   char *cache_nonce = NULL;
+   subkey_list_t subkey_list = NULL;  /* Track already processed subkeys. */
+   int skip_until_subkey = 0;
+diff --git a/g10/getkey.c b/g10/getkey.c
+index 21dcf08..961d7de 100644
+--- a/g10/getkey.c
++++ b/g10/getkey.c
+@@ -1640,7 +1640,8 @@ get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk,
+                   if (! ctx->kr_handle)
+                     {
+                       xfree (ctx);
+-                      *retctx = NULL;
++                      if (retctx)
++                        *retctx = NULL;
+                       rc = gpg_error_from_syserror ();
+                     }
+                   else
+diff --git a/g10/tofu.c b/g10/tofu.c
+index 39457a5..c3a4988 100644
+--- a/g10/tofu.c
++++ b/g10/tofu.c
+@@ -3857,7 +3857,7 @@ tofu_get_validity (ctrl_t ctrl, PKT_public_key *pk, strlist_t user_id_list,
+ gpg_error_t
+ tofu_set_policy (ctrl_t ctrl, kbnode_t kb, enum tofu_policy policy)
+ {
+-  gpg_error_t err;
++  gpg_error_t err = 0;
+   time_t now = gnupg_get_time ();
+   tofu_dbs_t dbs;
+   PKT_public_key *pk;
diff -Nru gnupg2-2.1.18/debian/patches/0073-dirmngr-Fix-final-close-of-LISTEN_FD.patch gnupg2-2.1.18/debian/patches/0073-dirmngr-Fix-final-close-of-LISTEN_FD.patch
--- gnupg2-2.1.18/debian/patches/0073-dirmngr-Fix-final-close-of-LISTEN_FD.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0073-dirmngr-Fix-final-close-of-LISTEN_FD.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,52 @@
+From: NIIBE Yutaka <gniibe at fsij.org>
+Date: Tue, 18 Apr 2017 09:04:11 +0900
+Subject: dirmngr: Fix final close of LISTEN_FD.
+
+* dirmngr/dirmngr.c (handle_connections): Close LISTEN_FD.
+
+Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>
+(cherry picked from commit 4b2581dc0ea1d03e70023bb0748aa0c21c0a2173)
+---
+ dirmngr/dirmngr.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
+index 31d3ca2..513e2a6 100644
+--- a/dirmngr/dirmngr.c
++++ b/dirmngr/dirmngr.c
+@@ -1905,7 +1905,6 @@ handle_connections (assuan_fd_t listen_fd)
+ #endif
+   struct sockaddr_un paddr;
+   socklen_t plen = sizeof( paddr );
+-  gnupg_fd_t fd;
+   int nfd, ret;
+   fd_set fdset, read_fdset;
+   int saved_errno;
+@@ -2030,6 +2029,8 @@ handle_connections (assuan_fd_t listen_fd)
+ 
+       if (FD_ISSET (FD2INT (listen_fd), &read_fdset))
+ 	{
++          gnupg_fd_t fd;
++
+           plen = sizeof paddr;
+ 	  fd = INT2FD (npth_accept (FD2INT(listen_fd),
+ 				    (struct sockaddr *)&paddr, &plen));
+@@ -2058,7 +2059,6 @@ handle_connections (assuan_fd_t listen_fd)
+                 }
+ 	      npth_setname_np (thread, threadname);
+             }
+-          fd = GNUPG_INVALID_FD;
+ 	}
+     }
+ 
+@@ -2067,8 +2067,8 @@ handle_connections (assuan_fd_t listen_fd)
+     close (my_inotify_fd);
+ #endif /*HAVE_INOTIFY_INIT*/
+   npth_attr_destroy (&tattr);
+-  if (listen_fd != -1)
+-    assuan_sock_close (fd);
++  if (listen_fd != GNUPG_INVALID_FD)
++    assuan_sock_close (listen_fd);
+   cleanup ();
+   log_info ("%s %s stopped\n", strusage(11), strusage(13));
+ }
diff -Nru gnupg2-2.1.18/debian/patches/0074-g10-invalidate-the-fd-cache-for-keyring.patch gnupg2-2.1.18/debian/patches/0074-g10-invalidate-the-fd-cache-for-keyring.patch
--- gnupg2-2.1.18/debian/patches/0074-g10-invalidate-the-fd-cache-for-keyring.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0074-g10-invalidate-the-fd-cache-for-keyring.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,41 @@
+From: NIIBE Yutaka <gniibe at fsij.org>
+Date: Tue, 25 Apr 2017 07:48:51 +0900
+Subject: g10: invalidate the fd cache for keyring.
+
+* g10/keyring.c (keyring_search_reset): Don't keep the FD cache.
+
+--
+
+GnuPG-bug-id: 3096
+Fixes-commit: 5556eca5acd46983bff0b38a1ffbc2f07fbaba9f
+Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>
+(cherry picked from commit 116cfd60779fbb3540da629db54dc2e148f4a3a2)
+---
+ g10/keyring.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/g10/keyring.c b/g10/keyring.c
+index 328290e..d75fdbc 100644
+--- a/g10/keyring.c
++++ b/g10/keyring.c
+@@ -692,7 +692,6 @@ keyring_search_reset (KEYRING_HANDLE hd)
+ {
+     log_assert (hd);
+ 
+-    hd->current.kr = NULL;
+     iobuf_close (hd->current.iobuf);
+     hd->current.iobuf = NULL;
+     hd->current.eof = 0;
+@@ -700,6 +699,12 @@ keyring_search_reset (KEYRING_HANDLE hd)
+ 
+     hd->found.kr = NULL;
+     hd->found.offset = 0;
++
++    if (hd->current.kr)
++      iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0,
++                   (char*)hd->current.kr->fname);
++    hd->current.kr = NULL;
++
+     return 0;
+ }
+ 
diff -Nru gnupg2-2.1.18/debian/patches/0075-dirmngr-Fix-aliasing-problem-in-dns.c.patch gnupg2-2.1.18/debian/patches/0075-dirmngr-Fix-aliasing-problem-in-dns.c.patch
--- gnupg2-2.1.18/debian/patches/0075-dirmngr-Fix-aliasing-problem-in-dns.c.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/0075-dirmngr-Fix-aliasing-problem-in-dns.c.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,89 @@
+From: NIIBE Yutaka <gniibe at fsij.org>
+Date: Tue, 25 Apr 2017 21:00:41 +0900
+Subject: dirmngr: Fix aliasing problem in dns.c.
+
+* dirmngr/dns.c (dns_ai_setent): Care about aliasing.
+
+--
+
+Co-authored-by: Tomas Mraz
+GnuPG-bug-id: 3105
+Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>
+(cherry picked from commit 247932f367f856e7ce91528e14f0aaf838150857)
+---
+ dirmngr/dns.c | 34 ++++++++++++++++++----------------
+ 1 file changed, 18 insertions(+), 16 deletions(-)
+
+diff --git a/dirmngr/dns.c b/dirmngr/dns.c
+index ebfd4c3..866f69d 100644
+--- a/dirmngr/dns.c
++++ b/dirmngr/dns.c
+@@ -9440,29 +9440,31 @@ void dns_ai_close(struct dns_addrinfo *ai) {
+ 
+ 
+ static int dns_ai_setent(struct addrinfo **ent, union dns_any *any, enum dns_type type, struct dns_addrinfo *ai) {
+-	struct sockaddr *saddr;
+-	struct sockaddr_in sin;
+-	struct sockaddr_in6 sin6;
++	union u {
++		struct sockaddr_in sin;
++		struct sockaddr_in6 sin6;
++		struct sockaddr_storage ss;
++	} addr;
+ 	const char *cname;
+ 	size_t clen;
+ 
+ 	switch (type) {
+ 	case DNS_T_A:
+-		saddr	= memset(&sin, '\0', sizeof sin);
++		memset(&addr.sin, '\0', sizeof addr.sin);
+ 
+-		sin.sin_family	= AF_INET;
+-		sin.sin_port	= htons(ai->port);
++		addr.sin.sin_family	= AF_INET;
++		addr.sin.sin_port	= htons(ai->port);
+ 
+-		memcpy(&sin.sin_addr, any, sizeof sin.sin_addr);
++		memcpy(&addr.sin.sin_addr, any, sizeof addr.sin.sin_addr);
+ 
+ 		break;
+ 	case DNS_T_AAAA:
+-		saddr	= memset(&sin6, '\0', sizeof sin6);
++		memset(&addr.sin6, '\0', sizeof addr.sin6);
+ 
+-		sin6.sin6_family	= AF_INET6;
+-		sin6.sin6_port		= htons(ai->port);
++		addr.sin6.sin6_family	= AF_INET6;
++		addr.sin6.sin6_port	= htons(ai->port);
+ 
+-		memcpy(&sin6.sin6_addr, any, sizeof sin6.sin6_addr);
++		memcpy(&addr.sin6.sin6_addr, any, sizeof addr.sin6.sin6_addr);
+ 
+ 		break;
+ 	default:
+@@ -9477,20 +9479,20 @@ static int dns_ai_setent(struct addrinfo **ent, union dns_any *any, enum dns_typ
+ 		clen	= 0;
+ 	}
+ 
+-	if (!(*ent = malloc(sizeof **ent + dns_sa_len(saddr) + ((ai->hints.ai_flags & AI_CANONNAME)? clen + 1 : 0))))
++	if (!(*ent = malloc(sizeof **ent + dns_sa_len(&addr) + ((ai->hints.ai_flags & AI_CANONNAME)? clen + 1 : 0))))
+ 		return dns_syerr();
+ 
+ 	memset(*ent, '\0', sizeof **ent);
+ 
+-	(*ent)->ai_family	= saddr->sa_family;
++	(*ent)->ai_family	= addr.ss.ss_family;
+ 	(*ent)->ai_socktype	= ai->hints.ai_socktype;
+ 	(*ent)->ai_protocol	= ai->hints.ai_protocol;
+ 
+-	(*ent)->ai_addr		= memcpy((unsigned char *)*ent + sizeof **ent, saddr, dns_sa_len(saddr));
+-	(*ent)->ai_addrlen	= dns_sa_len(saddr);
++	(*ent)->ai_addr		= memcpy((unsigned char *)*ent + sizeof **ent, &addr, dns_sa_len(&addr));
++	(*ent)->ai_addrlen	= dns_sa_len(&addr);
+ 
+ 	if (ai->hints.ai_flags & AI_CANONNAME)
+-		(*ent)->ai_canonname	= memcpy((unsigned char *)*ent + sizeof **ent + dns_sa_len(saddr), cname, clen + 1);
++		(*ent)->ai_canonname	= memcpy((unsigned char *)*ent + sizeof **ent + dns_sa_len(&addr), cname, clen + 1);
+ 
+ 	ai->found++;
+ 
diff -Nru gnupg2-2.1.18/debian/patches/avoid-spurious-warnings/0078-gpg-Avoid-spurious-warnings-about-trust-packets.patch gnupg2-2.1.18/debian/patches/avoid-spurious-warnings/0078-gpg-Avoid-spurious-warnings-about-trust-packets.patch
--- gnupg2-2.1.18/debian/patches/avoid-spurious-warnings/0078-gpg-Avoid-spurious-warnings-about-trust-packets.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/avoid-spurious-warnings/0078-gpg-Avoid-spurious-warnings-about-trust-packets.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,39 @@
+From: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
+Date: Fri, 5 May 2017 22:37:23 -0400
+Subject: gpg: Avoid spurious warnings about trust packets.
+
+* g10/keydb.c (parse_keyblock_image): Do not emit a warning when
+skipping a trust packet.
+
+--
+
+2.1.20 and later store trust packets in the keybox.  If an older
+version (like 2.1.18) ends up accessing a keybox that 2.1.20 or later
+has used, it produces many spurious warnings like:
+
+    gpg: skipped packet of type 12 in keybox
+
+This is a temporary cleanup to avoid these specific warnings; it can
+be dropped when moving to 2.1.20 or later.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
+---
+ g10/keydb.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/g10/keydb.c b/g10/keydb.c
+index aab90e3..81dd32e 100644
+--- a/g10/keydb.c
++++ b/g10/keydb.c
+@@ -1205,8 +1205,9 @@ parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no,
+         default:
+           /* Note that can't allow ring trust packets here and some of
+              the other GPG specific packets don't make sense either.  */
+-          log_error ("skipped packet of type %d in keybox\n",
+-                     (int)pkt->pkttype);
++          if (pkt->pkttype != PKT_RING_TRUST)
++            log_error ("skipped packet of type %d in keybox\n",
++                       (int)pkt->pkttype);
+           free_packet(pkt);
+           init_packet(pkt);
+           continue;
diff -Nru gnupg2-2.1.18/debian/patches/series gnupg2-2.1.18/debian/patches/series
--- gnupg2-2.1.18/debian/patches/series	2017-02-13 09:12:56.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/series	2017-05-08 16:44:18.000000000 -0400
@@ -27,3 +27,52 @@
 0027-doc-Clarify-abbreviation-of-help.patch
 0028-scd-Backport-two-fixes-from-master.patch
 0029-scd-Fix-use-case-of-PC-SC.patch
+0030-scd-Fix-factory-reset.patch
+0031-gpg-Fix-aliases-list-key-list-sig-and-check-sig.patch
+0032-gpg-common-Make-sure-that-all-fd-given-are-valid.patch
+0033-common-Avoid-warning-about-implicit-declaration-of-g.patch
+0034-gpg-Fix-memory-leak-in-the-error-case-of-signature-c.patch
+0035-gpg-Print-a-warning-if-no-command-has-been-given.patch
+0036-gpgconf-No-ENOENT-warning-with-change-options-et-al.patch
+0037-dirmngr-Do-a-DNS-lookup-even-if-it-is-missing-from-n.patch
+0038-gpg-Make-export-ssh-key-work-for-the-primary-key.patch
+0039-dirmngr-Avoid-PTR-lookup-for-hosts-in-a-pool.patch
+0040-gpgv-w32-Fix-status-fd.patch
+0041-gpg-tools-Make-trust-model-configurable-via-gpgconf.patch
+0042-gpg-tools-Make-auto-key-retrieve-configurable-via-gp.patch
+0043-gpg-Allow-creating-keys-using-an-existing-ECC-key.patch
+0044-gpg-Make-export-options-work-with-export-secret-keys.patch
+0045-common-tools-Always-escape-newlines-when-escaping-da.patch
+0046-g10-Signal-an-error-when-trying-to-revoke-non-exista.patch
+0047-gpg-Fix-possible-segv-when-attribute-packets-are-fil.patch
+0048-gpg-Fix-attempt-to-double-free-an-UID-structure.patch
+0049-doc-Add-a-note-to-the-trust-model-direct.patch
+0050-gpg-Flush-stdout-before-printing-stats-with-check-si.patch
+0051-dirmngr-Ignore-warning-alerts-in-the-GNUTLS-handshak.patch
+0052-gpg-Make-sure-the-conflict-set-includes-the-current-.patch
+0053-dirmngr-Load-the-hosts-file-into-libdns.patch
+0054-dirmngr-Fix-error-handling.patch
+0055-common-Implicitly-do-a-gpgconf-create-socketdir.patch
+0056-common-Fix-connecting-to-the-agent.patch
+0057-g10-Fix-memory-leak.patch
+0058-common-Avoid-undefined-behavior.patch
+0059-gpg-Handle-critical-marked-Reason-for-Revocation.patch
+0060-dirmngr-Do-not-assume-that-etc-hosts-exists.patch
+0061-dirmngr-Always-print-a-warning-for-a-missing-etc-hos.patch
+0062-dirmngr-Handle-EIO-which-is-sometimes-returned-by-co.patch
+0063-dirmngr-New-option-disable-ipv6.patch
+0064-agent-Serialize-access-to-passphrase-cache.patch
+0065-gpg-Fix-printing-of-offline-taken-subkey.patch
+0066-doc-Explain-the-in-a-key-listing.patch
+0067-dirmngr-Fix-possible-null-reference.patch
+0068-tools-Fix-condition-for-gpg-connect-agent.patch
+0069-dirmngr-Fix-alignment-of-ADDR.patch
+0070-dirmngr-Fix-http.c-for-sockaddr_storage.patch
+0071-g10-Fix-import-export-filter-property-match.patch
+0072-g10-Minor-fixes.patch
+0073-dirmngr-Fix-final-close-of-LISTEN_FD.patch
+0074-g10-invalidate-the-fd-cache-for-keyring.patch
+0075-dirmngr-Fix-aliasing-problem-in-dns.c.patch
+skip-missing-signing-keys/0076-g10-Skip-signing-keys-where-no-secret-key-is-availab.patch
+skel-file-removal/0077-g10-remove-skeleton-options-files.patch
+avoid-spurious-warnings/0078-gpg-Avoid-spurious-warnings-about-trust-packets.patch
diff -Nru gnupg2-2.1.18/debian/patches/skel-file-removal/0077-g10-remove-skeleton-options-files.patch gnupg2-2.1.18/debian/patches/skel-file-removal/0077-g10-remove-skeleton-options-files.patch
--- gnupg2-2.1.18/debian/patches/skel-file-removal/0077-g10-remove-skeleton-options-files.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/skel-file-removal/0077-g10-remove-skeleton-options-files.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,440 @@
+From: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
+Date: Mon, 17 Apr 2017 10:51:55 -0400
+Subject: g10: remove skeleton options files
+
+* build-aux/speed/w32/inst.nsi: stop installing skeleton files.
+* doc/gpg.texi: stop documenting skeleton files.
+* g10/Makefile.am: stop installing skeleton files.
+* g10/openfile.c (copy_options_file): Remove.
+(try_make_homedir): do not call copy_options_file()
+
+The defaults for gpg and dirmngr are good.  Both programs should work
+fine for the simple case without any config file.  The skeleton config
+files were being copied at first use (when the defaults are fine).
+But when the user needs to fiddle with them (after they've become
+sophisticated users), they're likely out of date because gpg has been
+upgraded since then.  So they're used for documentation, but they're
+stale documentation, which is probably worse than a clean empty file.
+
+--
+
+GnuPG-bug-id: 3086
+Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
+---
+ build-aux/speedo/w32/inst.nsi |   2 -
+ doc/gpg.texi                  |   4 --
+ g10/Makefile.am               |   8 +--
+ g10/dirmngr-conf.skel         |  69 ---------------------
+ g10/openfile.c                | 102 -------------------------------
+ g10/options.skel              | 139 ------------------------------------------
+ 6 files changed, 1 insertion(+), 323 deletions(-)
+ delete mode 100644 g10/dirmngr-conf.skel
+ delete mode 100644 g10/options.skel
+
+diff --git a/build-aux/speedo/w32/inst.nsi b/build-aux/speedo/w32/inst.nsi
+index 164e26b..779c759 100644
+--- a/build-aux/speedo/w32/inst.nsi
++++ b/build-aux/speedo/w32/inst.nsi
+@@ -607,8 +607,6 @@ Section "GnuPG" SEC_gnupg
+       Rename /REBOOTOK scdaemon.exe.tmp scdaemon.exe
+ 
+   SetOutPath "$INSTDIR\share\gnupg"
+-  File "share/gnupg/gpg-conf.skel"
+-  File "share/gnupg/dirmngr-conf.skel"
+   File "share/gnupg/distsigkey.gpg"
+ 
+   SetOutPath "$INSTDIR\share\locale\ca\LC_MESSAGES"
+diff --git a/doc/gpg.texi b/doc/gpg.texi
+index c591049..a7d78c4 100644
+--- a/doc/gpg.texi
++++ b/doc/gpg.texi
+@@ -3452,10 +3452,6 @@ files; They all live in in the current home directory (@pxref{option
+   You should backup all files in this directory and take care to keep
+   this backup closed away.
+ 
+-  @item @value{DATADIR}/options.skel
+-  @efindex options.skel
+-  The skeleton options file.
+-
+ @end table
+ 
+ Operation is further controlled by a few environment variables:
+diff --git a/g10/Makefile.am b/g10/Makefile.am
+index 604be93..19c5c78 100644
+--- a/g10/Makefile.am
++++ b/g10/Makefile.am
+@@ -18,7 +18,7 @@
+ 
+ ## Process this file with automake to produce Makefile.in
+ 
+-EXTRA_DIST = options.skel dirmngr-conf.skel distsigkey.gpg \
++EXTRA_DIST = distsigkey.gpg \
+ 	     ChangeLog-2011 gpg-w32info.rc \
+ 	     gpg.w32-manifest.in test.c t-keydb-keyring.kbx \
+ 	     t-keydb-get-keyblock.gpg t-stutter-data.asc
+@@ -238,18 +238,12 @@ install-exec-hook:
+ 
+ install-data-local:
+ 	$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
+-	$(INSTALL_DATA) $(srcdir)/options.skel \
+-				$(DESTDIR)$(pkgdatadir)/gpg-conf.skel
+-	$(INSTALL_DATA) $(srcdir)/dirmngr-conf.skel \
+-				$(DESTDIR)$(pkgdatadir)/dirmngr-conf.skel
+ 	$(INSTALL_DATA) $(srcdir)/distsigkey.gpg \
+ 				$(DESTDIR)$(pkgdatadir)/distsigkey.gpg
+ 
+ # NB: For uninstalling gpg and gpgv we use -local because there is
+ # no need for a specific order the targets need to be run.
+ uninstall-local:
+-	- at rm $(DESTDIR)$(pkgdatadir)/gpg-conf.skel
+-	- at rm $(DESTDIR)$(pkgdatadir)/dirmngr-conf.skel
+ 	- at rm $(DESTDIR)$(pkgdatadir)/distsigkey.gpg
+ 	- at files=`for p in $(gpg2_hack_uninst); do echo "$$p"; done | \
+ 	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+diff --git a/g10/dirmngr-conf.skel b/g10/dirmngr-conf.skel
+deleted file mode 100644
+index fbb730b..0000000
+--- a/g10/dirmngr-conf.skel
++++ /dev/null
+@@ -1,69 +0,0 @@
+-# dirmngr-conf.skel - Skeleton to create dirmngr.conf.
+-# (Note that the first three lines are not copied.)
+-#
+-# dirmngr.conf - Options for Dirmngr
+-# Written in 2015 by The GnuPG Project <https://gnupg.org>
+-#
+-# To the extent possible under law, the authors have dedicated all
+-# copyright and related and neighboring rights to this file to the
+-# public domain worldwide.  This file is distributed without any
+-# warranty.  You should have received a copy of the CC0 Public Domain
+-# Dedication along with this file. If not, see
+-# <http://creativecommons.org/publicdomain/zero/1.0/>.
+-#
+-#
+-# Unless you specify which option file to use (with the command line
+-# option "--options filename"), the file ~/.gnupg/dirmngr.conf is used
+-# by dirmngr.  The file can contain any long options which are valid
+-# for Dirmngr.  If the first non white space character of a line is a
+-# '#', the line is ignored.  Empty lines are also ignored.  See the
+-# dirmngr man page or the manual for a list of options.
+-#
+-
+-# --keyserver URI
+-#
+-# GPG can send and receive keys to and from a keyserver.  These
+-# servers can be HKP, Email, or LDAP (if GnuPG is built with LDAP
+-# support).
+-#
+-# Example HKP keyservers:
+-#      hkp://keys.gnupg.net
+-#
+-# Example HKP keyserver using a Tor OnionBalance service
+-#      hkp://jirk5u4osbsr34t5.onion
+-#
+-# Example HKPS keyservers (see --hkp-cacert below):
+-#       hkps://hkps.pool.sks-keyservers.net
+-#
+-# Example LDAP keyservers:
+-#      ldap://pgp.surfnet.nl:11370
+-#
+-# Regular URL syntax applies, and you can set an alternate port
+-# through the usual method:
+-#      hkp://keyserver.example.net:22742
+-#
+-# Most users just set the name and type of their preferred keyserver.
+-# Note that most servers (with the notable exception of
+-# ldap://keyserver.pgp.com) synchronize changes with each other.  Note
+-# also that a single server name may actually point to multiple
+-# servers via DNS round-robin.  hkp://keys.gnupg.net is an example of
+-# such a "server", which spreads the load over a number of physical
+-# servers.
+-#
+-# If exactly two keyservers are configured and only one is a Tor hidden
+-# service, Dirmngr selects the keyserver to use depending on whether
+-# Tor is locally running or not (on a per session base).
+-
+-keyserver hkp://jirk5u4osbsr34t5.onion
+-keyserver hkp://keys.gnupg.net
+-
+-# --hkp-cacert FILENAME
+-#
+-# For the "hkps" scheme (keyserver access over TLS), Dirmngr needs to
+-# know the root certificates for verification of the TLS certificates
+-# used for the connection.  Enter the full name of a file with the
+-# root certificates here.  If that file is in PEM format a ".pem"
+-# suffix is expected.  This option may be given multiple times to add
+-# more root certificates.  Tilde expansion is supported.
+-
+-#hkp-cacert /path/to/CA/sks-keyservers.netCA.pem
+diff --git a/g10/openfile.c b/g10/openfile.c
+index f62deec..2e8c102 100644
+--- a/g10/openfile.c
++++ b/g10/openfile.c
+@@ -36,12 +36,6 @@
+ #include "status.h"
+ #include "i18n.h"
+ 
+-#ifdef USE_ONLY_8DOT3
+-#define SKELEXT ".skl"
+-#else
+-#define SKELEXT EXTSEP_S "skel"
+-#endif
+-
+ #ifdef HAVE_W32_SYSTEM
+ #define NAME_OF_DEV_NULL "nul"
+ #else
+@@ -373,93 +367,6 @@ open_sigfile (const char *sigfilename, progress_filter_context_t *pfx)
+ }
+ 
+ 
+-/****************
+- * Copy the option file skeleton for NAME to the given directory.
+- * Returns true if the new option file has any option.
+- */
+-static int
+-copy_options_file (const char *destdir, const char *name)
+-{
+-  const char *datadir = gnupg_datadir ();
+-  char *fname;
+-  FILE *src, *dst;
+-  int linefeeds=0;
+-  int c;
+-  mode_t oldmask;
+-  int esc = 0;
+-  int any_option = 0;
+-
+-  if (opt.dry_run)
+-    return 0;
+-
+-  fname = xstrconcat (datadir, DIRSEP_S, name, "-conf", SKELEXT, NULL);
+-  src = fopen (fname, "r");
+-  if (src && is_secured_file (fileno (src)))
+-    {
+-      fclose (src);
+-      src = NULL;
+-      gpg_err_set_errno (EPERM);
+-    }
+-  if (!src)
+-    {
+-      log_info (_("can't open '%s': %s\n"), fname, strerror(errno));
+-      xfree(fname);
+-      return 0;
+-    }
+-  xfree (fname);
+-  fname = xstrconcat (destdir, DIRSEP_S, name, EXTSEP_S, "conf", NULL);
+-
+-  oldmask = umask (077);
+-  if (is_secured_filename (fname))
+-    {
+-      dst = NULL;
+-      gpg_err_set_errno (EPERM);
+-    }
+-  else
+-    dst = fopen( fname, "w" );
+-  umask (oldmask);
+-
+-  if (!dst)
+-    {
+-      log_info (_("can't create '%s': %s\n"), fname, strerror(errno) );
+-      fclose (src);
+-      xfree (fname);
+-      return 0;
+-    }
+-
+-  while ((c = getc (src)) != EOF)
+-    {
+-      if (linefeeds < 3)
+-        {
+-          if (c == '\n')
+-            linefeeds++;
+-	}
+-      else
+-        {
+-          putc (c, dst);
+-          if (c== '\n')
+-            esc = 1;
+-          else if (esc == 1)
+-            {
+-              if (c == ' ' || c == '\t')
+-                ;
+-              else if (c == '#')
+-                esc = 2;
+-              else
+-                any_option = 1;
+-            }
+-        }
+-    }
+-
+-  fclose (dst);
+-  fclose (src);
+-
+-  log_info (_("new configuration file '%s' created\n"), fname);
+-  xfree (fname);
+-  return any_option;
+-}
+-
+-
+ void
+ try_make_homedir (const char *fname)
+ {
+@@ -489,15 +396,6 @@ try_make_homedir (const char *fname)
+                     fname, strerror(errno) );
+       else if (!opt.quiet )
+         log_info ( _("directory '%s' created\n"), fname );
+-
+-      /* Note that we also copy a dirmngr.conf file here.  This is
+-         because gpg is likely the first invoked tool and thus creates
+-         the directory.  */
+-      copy_options_file (fname, DIRMNGR_NAME);
+-      if (copy_options_file (fname, GPG_NAME))
+-        log_info (_("WARNING: options in '%s'"
+-                    " are not yet active during this run\n"),
+-                  fname);
+     }
+ }
+ 
+diff --git a/g10/options.skel b/g10/options.skel
+deleted file mode 100644
+index 87fc627..0000000
+--- a/g10/options.skel
++++ /dev/null
+@@ -1,139 +0,0 @@
+-# These first three lines are not copied to the gpg.conf file in
+-# the users home directory.
+-# $Id$
+-# Options for GnuPG
+-# Copyright 1998-2003, 2010 Free Software Foundation, Inc.
+-# Copyright 1998-2003, 2010 Werner Koch
+-#
+-# This file is free software; as a special exception the author gives
+-# unlimited permission to copy and/or distribute it, with or without
+-# modifications, as long as this notice is preserved.
+-#
+-# This file is distributed in the hope that it will be useful, but
+-# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+-#
+-# Unless you specify which option file to use (with the command line
+-# option "--options filename"), GnuPG uses the file ~/.gnupg/gpg.conf
+-# by default.
+-#
+-# An options file can contain any long options which are available in
+-# GnuPG. If the first non white space character of a line is a '#',
+-# this line is ignored.  Empty lines are also ignored.
+-#
+-# See the gpg man page for a list of options.
+-
+-
+-# If you have more than 1 secret key in your keyring, you may want to
+-# uncomment the following option and set your preferred keyid.
+-
+-#default-key 621CC013
+-
+-
+-# If you do not pass a recipient to gpg, it will ask for one.  Using
+-# this option you can encrypt to a default key.  Key validation will
+-# not be done in this case.  The second form uses the default key as
+-# default recipient.
+-
+-#default-recipient some-user-id
+-#default-recipient-self
+-
+-
+-# Group names may be defined like this:
+-#   group mynames = paige 0x12345678 joe patti
+-#
+-# Any time "mynames" is a recipient (-r or --recipient), it will be
+-# expanded to the names "paige", "joe", and "patti", and the key ID
+-# "0x12345678".  Note there is only one level of expansion - you
+-# cannot make an group that points to another group.  Note also that
+-# if there are spaces in the recipient name, this will appear as two
+-# recipients.  In these cases it is better to use the key ID.
+-
+-#group mynames = paige 0x12345678 joe patti
+-
+-
+-# GnuPG can automatically locate and retrieve keys as needed using
+-# this option.  This happens when encrypting to an email address (in
+-# the "user@@example.com" form) and there are no keys matching
+-# "user at example.com" in the local keyring.  This option takes any
+-# number mechanisms which are tried in the given order.  The default
+-# is "--auto-key-locate local" to search for keys only in the local
+-# key database.  Uncomment the next line to locate a missing key using
+-# two DNS based mechanisms.
+-
+-#auto-key-locate local,pka,dane
+-
+-
+-# Common options for keyserver functions:
+-# (Note that the --keyserver option has been moved to dirmngr.conf)
+-#
+-# include-disabled = when searching, include keys marked as "disabled"
+-#                    on the keyserver (not all keyservers support this).
+-#
+-# no-include-revoked = when searching, do not include keys marked as
+-#                      "revoked" on the keyserver.
+-#
+-# verbose = show more information as the keys are fetched.
+-#           Can be used more than once to increase the amount
+-#           of information shown.
+-#
+-# auto-key-retrieve = automatically fetch keys as needed from the keyserver
+-#                     when verifying signatures or when importing keys that
+-#                     have been revoked by a revocation key that is not
+-#                     present on the keyring.
+-#
+-# no-include-attributes = do not include attribute IDs (aka "photo IDs")
+-#                         when sending keys to the keyserver.
+-
+-#keyserver-options auto-key-retrieve
+-
+-
+-# Uncomment this line to display photo user IDs in key listings and
+-# when a signature from a key with a photo is verified.
+-
+-#show-photos
+-
+-
+-# Use this program to display photo user IDs
+-#
+-# %i is expanded to a temporary file that contains the photo.
+-# %I is the same as %i, but the file isn't deleted afterwards by GnuPG.
+-# %k is expanded to the key ID of the key.
+-# %K is expanded to the long OpenPGP key ID of the key.
+-# %t is expanded to the extension of the image (e.g. "jpg").
+-# %T is expanded to the MIME type of the image (e.g. "image/jpeg").
+-# %f is expanded to the fingerprint of the key.
+-# %% is %, of course.
+-#
+-# If %i or %I are not present, then the photo is supplied to the
+-# viewer on standard input.  If your platform supports it, standard
+-# input is the best way to do this as it avoids the time and effort in
+-# generating and then cleaning up a secure temp file.
+-#
+-# The default program is "xloadimage -fork -quiet -title 'KeyID 0x%k' stdin"
+-# On Mac OS X and Windows, the default is to use your regular JPEG image
+-# viewer.
+-#
+-# Some other viewers:
+-# photo-viewer "qiv %i"
+-# photo-viewer "ee %i"
+-# photo-viewer "display -title 'KeyID 0x%k'"
+-#
+-# This one saves a copy of the photo ID in your home directory:
+-# photo-viewer "cat > ~/photoid-for-key-%k.%t"
+-#
+-# Use your MIME handler to view photos:
+-# photo-viewer "metamail -q -d -b -c %T -s 'KeyID 0x%k' -f GnuPG"
+-
+-
+-# Because some mailers change lines starting with "From " to ">From "
+-# it is good to handle such lines in a special way when creating
+-# cleartext signatures; all other PGP versions do it this way too.
+-# To enable full OpenPGP compliance you may want to use this option.
+-
+-#no-escape-from-lines
+-
+-
+-# Uncomment the following option to get rid of the copyright notice
+-
+-#no-greeting
diff -Nru gnupg2-2.1.18/debian/patches/skip-missing-signing-keys/0076-g10-Skip-signing-keys-where-no-secret-key-is-availab.patch gnupg2-2.1.18/debian/patches/skip-missing-signing-keys/0076-g10-Skip-signing-keys-where-no-secret-key-is-availab.patch
--- gnupg2-2.1.18/debian/patches/skip-missing-signing-keys/0076-g10-Skip-signing-keys-where-no-secret-key-is-availab.patch	1969-12-31 19:00:00.000000000 -0500
+++ gnupg2-2.1.18/debian/patches/skip-missing-signing-keys/0076-g10-Skip-signing-keys-where-no-secret-key-is-availab.patch	2017-05-08 16:44:18.000000000 -0400
@@ -0,0 +1,51 @@
+From: Simon Arlott <simon at arlott.org>
+Date: Sun, 5 Feb 2017 16:31:35 -0500
+Subject: g10: Skip signing keys where no secret key is available.
+
+* g10/getkey.c (finish_lookup): When requiring PUBKEY_USAGE_SIG, skip
+over keys where no signing key is available.
+
+--
+
+This should only be relevant when gpg is required to choose which key
+to sign with -- if verifying signatures, we already know which subkey
+to look at, and indeed gpg doesn't seem to have a problem with this.
+
+This patch comes from
+https://bugs.gnupg.org/gnupg/file793/sign-fix.patch
+
+I (dkg) have reviewed and tested it with missing local keys, and it
+makes sense to me as the default behavior.  If the user has the secret
+key for a signing-capable subkey available and the command is --sign,
+it should be used.
+
+If the user has explicitly specified a subkey that happens to be
+missing (e.g. with the trailing ! for --default-key 0x${FPR}!) then
+this does not override that behavior (the signature will still fail).
+
+GnuPG-bug-id: 1967
+Debian-bug-id: 834922
+
+Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
+---
+ g10/getkey.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/g10/getkey.c b/g10/getkey.c
+index 961d7de..bb31dfb 100644
+--- a/g10/getkey.c
++++ b/g10/getkey.c
+@@ -3529,6 +3529,13 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
+ 	      continue;
+ 	    }
+ 
++	  if ((req_usage & PUBKEY_USAGE_SIG) && agent_probe_secret_key (NULL, pk))
++	    {
++	      if (DBG_LOOKUP)
++		log_debug ("\tno secret key for signing\n");
++	      continue;
++	    }
++
+ 	  if (DBG_LOOKUP)
+ 	    log_debug ("\tsubkey might be fine\n");
+ 	  /* In case a key has a timestamp of 0 set, we make sure


More information about the pkg-gnupg-maint mailing list