summaryrefslogtreecommitdiffstats
path: root/debian/patches
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 09:59:16 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 09:59:16 +0000
commitabd376d1e24e6665ef3662eb23ad76adadf78f72 (patch)
treeec7213f75b7e8c9cdbb4d335ed9ca7c11aae6f5f /debian/patches
parentAdding upstream version 2.2.27. (diff)
downloadgnupg2-debian.tar.xz
gnupg2-debian.zip
Adding debian version 2.2.27-2+deb11u2.debian/2.2.27-2+deb11u2debian
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'debian/patches')
-rw-r--r--debian/patches/Make-gpg-zip-use-tar-from-PATH.patch27
-rw-r--r--debian/patches/Use-hkps-keys.openpgp.org-as-the-default-keyserver.patch71
-rw-r--r--debian/patches/block-ptrace-on-secret-daemons/Avoid-simple-memory-dumps-via-ptrace.patch89
-rw-r--r--debian/patches/cherry-picked/1617856888.gnupg-2.3.0-4-gab66c4357.scd-fix-ccid-driver-for-scm-spr332-spr532.patch48
-rw-r--r--debian/patches/cherry-picked/g10-Fix-garbled-status-messages-in-NOTATION_DATA.patch47
-rw-r--r--debian/patches/debian-packaging/avoid-beta-warning.patch44
-rw-r--r--debian/patches/debian-packaging/avoid-regenerating-defsincdate-use-shipped-file.patch39
-rw-r--r--debian/patches/dirmngr-Only-use-SKS-pool-CA-for-SKS-pool.patch29
-rw-r--r--debian/patches/dirmngr-idling/dirmngr-Avoid-automatically-checking-upstream-swdb.patch47
-rw-r--r--debian/patches/dirmngr-idling/dirmngr-Avoid-need-for-hkp-housekeeping.patch230
-rw-r--r--debian/patches/dirmngr-idling/dirmngr-hkp-Avoid-potential-race-condition-when-some.patch81
-rw-r--r--debian/patches/from-master/gpg-change-agent-spawn-2019-07-24-v2.patch50
-rw-r--r--debian/patches/from-master/gpg-default-to-3072-bit-keys.patch91
-rw-r--r--debian/patches/from-master/gpg-default-to-AES-256.patch35
-rw-r--r--debian/patches/gpg-agent-idling/agent-Allow-threads-to-interrupt-main-select-loop-wi.patch84
-rw-r--r--debian/patches/gpg-agent-idling/agent-Avoid-scheduled-checks-on-socket-when-inotify-.patch26
-rw-r--r--debian/patches/gpg-agent-idling/agent-Avoid-tight-timer-tick-when-possible.patch101
-rw-r--r--debian/patches/gpg-agent-idling/agent-Create-framework-of-scheduled-timers.patch191
-rw-r--r--debian/patches/gpg-drop-import-clean-from-default-keyserver-import-optio.patch49
-rw-r--r--debian/patches/import-merge-without-userid/gpg-accept-subkeys-with-a-good-revocation-but-no-self-sig.patch32
-rw-r--r--debian/patches/import-merge-without-userid/gpg-allow-import-of-previously-known-keys-even-without-UI.patch106
-rw-r--r--debian/patches/import-merge-without-userid/tests-add-test-cases-for-import-without-uid.patch201
-rw-r--r--debian/patches/series24
-rw-r--r--debian/patches/update-defaults/gpg-Default-to-SHA-512-for-all-signature-types-on-RS.patch64
-rw-r--r--debian/patches/update-defaults/gpg-Prefer-SHA-512-and-SHA-384-in-personal-digest.patch46
25 files changed, 1852 insertions, 0 deletions
diff --git a/debian/patches/Make-gpg-zip-use-tar-from-PATH.patch b/debian/patches/Make-gpg-zip-use-tar-from-PATH.patch
new file mode 100644
index 0000000..2deee94
--- /dev/null
+++ b/debian/patches/Make-gpg-zip-use-tar-from-PATH.patch
@@ -0,0 +1,27 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Sun, 18 Nov 2018 17:29:52 -0500
+Subject: Make gpg-zip use tar from $PATH
+
+Apparently there is no clean way to configure this from ./configure,
+and upstream is deprecating gpg-zip anyway. So just force-set tar to
+be manually "tar" (meaning, that we should look in the $PATH at
+runtime).
+
+See also https://dev.gnupg.org/T4251 and https://bugs.debian.org/913582
+---
+ tools/gpg-zip.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/gpg-zip.in b/tools/gpg-zip.in
+index 9047e36..3821f3a 100644
+--- a/tools/gpg-zip.in
++++ b/tools/gpg-zip.in
+@@ -23,7 +23,7 @@
+ # the GNU or POSIX variant of USTAR.
+
+ VERSION=@VERSION@
+-TAR=@TAR@
++TAR=tar
+ GPG=gpg
+
+ usage="\
diff --git a/debian/patches/Use-hkps-keys.openpgp.org-as-the-default-keyserver.patch b/debian/patches/Use-hkps-keys.openpgp.org-as-the-default-keyserver.patch
new file mode 100644
index 0000000..ce69403
--- /dev/null
+++ b/debian/patches/Use-hkps-keys.openpgp.org-as-the-default-keyserver.patch
@@ -0,0 +1,71 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Thu, 11 Jul 2019 21:52:11 -0400
+Subject: Use hkps://keys.openpgp.org as the default keyserver
+
+As of 2.2.17, GnuPG will refuse to accept any third-party
+certifications from OpenPGP certificates pulled from the keyserver
+network.
+
+The SKS keyserver network currently has at least a dozen popular
+certificates which are flooded with enough unusable third-party
+certifications that they cannot be retrieved in any reasonable amount
+of time.
+
+The hkps://keys.openpgp.org keyserver installation offers HKPS,
+performs cryptographic validation, and by policy does not distribute
+third-party certifications anyway.
+
+It is not distributed or federated yet, unfortunately, but it is
+functional, which is more than can be said for the dying SKS pool.
+And given that GnuPG is going to reject all the third-party
+certifications anyway, there is no clear "web of trust" rationale for
+relying on the SKS pool.
+
+One sticking point is that keys.openpgp.org does not distribute user
+IDs unless the user has proven control of the associated e-mail
+address. This means that on standard upstream GnuPG, retrieving
+revocations or subkey updates of those certificates will fail, because
+upstream GnuPG ignores any incoming certificate without a user ID,
+even if it knows a user ID in the local copy of the certificate (see
+https://dev.gnupg.org/T4393).
+
+However, we have three patches in
+debian/patches/import-merge-without-userid/ that together fix that
+bug.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ configure.ac | 2 +-
+ doc/dirmngr.texi | 6 +++++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 4b9d908..47eb11c 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1856,7 +1856,7 @@ AC_DEFINE_UNQUOTED(SCDAEMON_SOCK_NAME, "S.scdaemon",
+ AC_DEFINE_UNQUOTED(DIRMNGR_SOCK_NAME, "S.dirmngr",
+ [The name of the dirmngr socket])
+ AC_DEFINE_UNQUOTED(DIRMNGR_DEFAULT_KEYSERVER,
+- "hkps://hkps.pool.sks-keyservers.net",
++ "hkps://keys.openpgp.org",
+ [The default keyserver for dirmngr to use, if none is explicitly given])
+
+ AC_DEFINE_UNQUOTED(GPGEXT_GPG, "gpg", [The standard binary file suffix])
+diff --git a/doc/dirmngr.texi b/doc/dirmngr.texi
+index 84a8d28..603a11a 100644
+--- a/doc/dirmngr.texi
++++ b/doc/dirmngr.texi
+@@ -329,7 +329,11 @@ whether Tor is locally running or not. The check for a running Tor is
+ done for each new connection.
+
+ If no keyserver is explicitly configured, dirmngr will use the
+-built-in default of @code{hkps://hkps.pool.sks-keyservers.net}.
++built-in default of @code{hkps://keys.openpgp.org}.
++
++Note that the above default is a Debian-specific choice. Upstream
++GnuPG prefers @code{hkps://hkps.pool.sks-keyservers.net}. See
++/usr/share/doc/gpgconf/NEWS.Debian.gz for more details.
+
+ Windows users with a keyserver running on their Active Directory
+ should use @code{ldap:///} for @var{name} to access this directory.
diff --git a/debian/patches/block-ptrace-on-secret-daemons/Avoid-simple-memory-dumps-via-ptrace.patch b/debian/patches/block-ptrace-on-secret-daemons/Avoid-simple-memory-dumps-via-ptrace.patch
new file mode 100644
index 0000000..a1ce6ea
--- /dev/null
+++ b/debian/patches/block-ptrace-on-secret-daemons/Avoid-simple-memory-dumps-via-ptrace.patch
@@ -0,0 +1,89 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Tue, 11 Aug 2015 20:28:26 -0400
+Subject: Avoid simple memory dumps via ptrace
+
+This avoids needing to setgid gpg-agent. It probably doesn't defend
+against all possible attacks, but it defends against one specific (and
+easy) one. If there are other protections we should do them too.
+
+This will make it slightly harder to debug the agent because the
+normal user won't be able to attach gdb to it directly while it runs.
+
+The remaining options for debugging are:
+
+ * launch the agent from gdb directly
+ * connect gdb to a running agent as the superuser
+
+Upstream bug: https://dev.gnupg.org/T1211
+---
+ agent/gpg-agent.c | 8 ++++++++
+ configure.ac | 2 +-
+ scd/scdaemon.c | 9 +++++++++
+ 3 files changed, 18 insertions(+), 1 deletion(-)
+
+diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
+index b167c34..5afcf11 100644
+--- a/agent/gpg-agent.c
++++ b/agent/gpg-agent.c
+@@ -50,6 +50,9 @@
+ # include <signal.h>
+ #endif
+ #include <npth.h>
++#ifdef HAVE_PRCTL
++# include <sys/prctl.h>
++#endif
+
+ #define INCLUDED_BY_MAIN_MODULE 1
+ #define GNUPG_COMMON_NEED_AFLOCAL
+@@ -1030,6 +1033,11 @@ main (int argc, char **argv )
+
+ early_system_init ();
+
++#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
++ /* Disable ptrace on Linux without sgid bit */
++ prctl(PR_SET_DUMPABLE, 0);
++#endif
++
+ /* Before we do anything else we save the list of currently open
+ file descriptors and the signal mask. This info is required to
+ do the exec call properly. We don't need it on Windows. */
+diff --git a/configure.ac b/configure.ac
+index 7a2d410..2d8b050 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1426,7 +1426,7 @@ AC_CHECK_FUNCS([atexit canonicalize_file_name clock_gettime ctermid \
+ ftruncate funlockfile getaddrinfo getenv getpagesize \
+ getpwnam getpwuid getrlimit getrusage gettimeofday \
+ gmtime_r inet_ntop inet_pton isascii lstat memicmp \
+- memmove memrchr mmap nl_langinfo pipe raise rand \
++ memmove memrchr mmap nl_langinfo pipe prctl raise rand \
+ setenv setlocale setrlimit sigaction sigprocmask \
+ stat stpcpy strcasecmp strerror strftime stricmp \
+ strlwr strncasecmp strpbrk strsep strtol strtoul \
+diff --git a/scd/scdaemon.c b/scd/scdaemon.c
+index 5c519f8..cab66a0 100644
+--- a/scd/scdaemon.c
++++ b/scd/scdaemon.c
+@@ -37,6 +37,9 @@
+ #include <unistd.h>
+ #include <signal.h>
+ #include <npth.h>
++#ifdef HAVE_PRCTL
++# include <sys/prctl.h>
++#endif
+
+ #define INCLUDED_BY_MAIN_MODULE 1
+ #define GNUPG_COMMON_NEED_AFLOCAL
+@@ -446,6 +449,12 @@ main (int argc, char **argv )
+ npth_t pipecon_handler;
+
+ early_system_init ();
++
++#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
++ /* Disable ptrace on Linux without sgid bit */
++ prctl(PR_SET_DUMPABLE, 0);
++#endif
++
+ set_strusage (my_strusage);
+ gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
+ /* Please note that we may running SUID(ROOT), so be very CAREFUL
diff --git a/debian/patches/cherry-picked/1617856888.gnupg-2.3.0-4-gab66c4357.scd-fix-ccid-driver-for-scm-spr332-spr532.patch b/debian/patches/cherry-picked/1617856888.gnupg-2.3.0-4-gab66c4357.scd-fix-ccid-driver-for-scm-spr332-spr532.patch
new file mode 100644
index 0000000..a54ff93
--- /dev/null
+++ b/debian/patches/cherry-picked/1617856888.gnupg-2.3.0-4-gab66c4357.scd-fix-ccid-driver-for-scm-spr332-spr532.patch
@@ -0,0 +1,48 @@
+Subject: Scd: Fix CCID driver for SCM SPR332/SPR532
+Origin: gnupg-2.3.0-4-gab66c4357
+Upstream-Author: NIIBE Yutaka <gniibe@fsij.org>
+Date: Thu Apr 8 13:41:28 2021 +0900
+Bug-Debian: https://bugs.debian.org/982546
+
+ * scd/ccid-driver.c (ccid_vendor_specific_pinpad_setup): New.
+ (ccid_vendor_specific_setup): Only send CLEAR_HALT.
+ (ccid_transceive_secure): Each time, use send_escape_cmd.
+
+ --
+
+ GnuPG-bug-id: 5297
+ Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
+
+--- a/scd/ccid-driver.c
++++ b/scd/ccid-driver.c
+@@ -1304,10 +1304,20 @@
+ {
+ if (handle->id_vendor == VENDOR_SCM && handle->id_product == SCM_SPR532)
+ {
++ libusb_clear_halt (handle->idev, handle->ep_intr);
++ }
++ return 0;
++}
++
++
++static int
++ccid_vendor_specific_pinpad_setup (ccid_driver_t handle)
++{
++ if (handle->id_vendor == VENDOR_SCM && handle->id_product == SCM_SPR532)
++ {
+ DEBUGOUT ("sending escape sequence to switch to a case 1 APDU\n");
+ send_escape_cmd (handle, (const unsigned char*)"\x80\x02\x00", 3,
+ NULL, 0, NULL);
+- libusb_clear_halt (handle->idev, handle->ep_intr);
+ }
+ return 0;
+ }
+@@ -3583,6 +3593,8 @@
+ if (pininfo->fixedlen < 0 || pininfo->fixedlen >= 16)
+ return CCID_DRIVER_ERR_NOT_SUPPORTED;
+
++ ccid_vendor_specific_pinpad_setup (handle);
++
+ msg = send_buffer;
+ msg[0] = cherry_mode? 0x89 : PC_to_RDR_Secure;
+ msg[5] = 0; /* slot */
diff --git a/debian/patches/cherry-picked/g10-Fix-garbled-status-messages-in-NOTATION_DATA.patch b/debian/patches/cherry-picked/g10-Fix-garbled-status-messages-in-NOTATION_DATA.patch
new file mode 100644
index 0000000..d66b346
--- /dev/null
+++ b/debian/patches/cherry-picked/g10-Fix-garbled-status-messages-in-NOTATION_DATA.patch
@@ -0,0 +1,47 @@
+From: Werner Koch <wk@gnupg.org>
+Date: Tue, 14 Jun 2022 11:33:27 +0200
+Subject: g10: Fix garbled status messages in NOTATION_DATA
+
+* g10/cpr.c (write_status_text_and_buffer): Fix off-by-one
+--
+
+Depending on the escaping and line wrapping the computed remaining
+buffer length could be wrong. Fixed by always using a break to
+terminate the escape detection loop. Might have happened for all
+status lines which may wrap.
+
+GnuPG-bug-id: T6027
+(cherry picked from commit 34c649b3601383cd11dbc76221747ec16fd68e1b)
+---
+ g10/cpr.c | 13 ++++---------
+ 1 file changed, 4 insertions(+), 9 deletions(-)
+
+diff --git a/g10/cpr.c b/g10/cpr.c
+index d502e8b..bc4b715 100644
+--- a/g10/cpr.c
++++ b/g10/cpr.c
+@@ -328,20 +328,15 @@ write_status_text_and_buffer (int no, const char *string,
+ }
+ first = 0;
+ }
+- for (esc=0, s=buffer, n=len; n && !esc; s++, n--)
++ for (esc=0, s=buffer, n=len; n; s++, n--)
+ {
+ if (*s == '%' || *(const byte*)s <= lower_limit
+ || *(const byte*)s == 127 )
+ esc = 1;
+ if (wrap && ++count > wrap)
+- {
+- dowrap=1;
+- break;
+- }
+- }
+- if (esc)
+- {
+- s--; n++;
++ dowrap=1;
++ if (esc || dowrap)
++ break;
+ }
+ if (s != buffer)
+ es_fwrite (buffer, s-buffer, 1, statusfp);
diff --git a/debian/patches/debian-packaging/avoid-beta-warning.patch b/debian/patches/debian-packaging/avoid-beta-warning.patch
new file mode 100644
index 0000000..5cb22e5
--- /dev/null
+++ b/debian/patches/debian-packaging/avoid-beta-warning.patch
@@ -0,0 +1,44 @@
+From: Debian GnuPG Maintainers <pkg-gnupg-maint@lists.alioth.debian.org>
+Date: Tue, 14 Apr 2015 10:02:31 -0400
+Subject: avoid-beta-warning
+
+avoid self-describing as a beta
+
+Using autoreconf against the source as distributed in tarball form
+invariably results in a package that thinks it's a "beta" package,
+which produces the "THIS IS A DEVELOPMENT VERSION" warning string.
+
+since we use dh_autoreconf, i need this patch to avoid producing
+builds that announce themselves as DEVELOPMENT VERSIONs.
+
+See discussion at:
+
+ http://lists.gnupg.org/pipermail/gnupg-devel/2014-November/029065.html
+---
+ autogen.sh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/autogen.sh b/autogen.sh
+index b238550..9b86d3f 100755
+--- a/autogen.sh
++++ b/autogen.sh
+@@ -229,7 +229,7 @@ if [ "$myhost" = "find-version" ]; then
+ esac
+
+ beta=no
+- if [ -e .git ]; then
++ if false; then
+ ingit=yes
+ tmp=$(git describe --match "${matchstr1}" --long 2>/dev/null)
+ tmp=$(echo "$tmp" | sed s/^"$package"//)
+@@ -245,8 +245,8 @@ if [ "$myhost" = "find-version" ]; then
+ rvd=$((0x$(echo ${rev} | dd bs=1 count=4 2>/dev/null)))
+ else
+ ingit=no
+- beta=yes
+- tmp="-unknown"
++ beta=no
++ tmp=""
+ rev="0000000"
+ rvd="0"
+ fi
diff --git a/debian/patches/debian-packaging/avoid-regenerating-defsincdate-use-shipped-file.patch b/debian/patches/debian-packaging/avoid-regenerating-defsincdate-use-shipped-file.patch
new file mode 100644
index 0000000..01489be
--- /dev/null
+++ b/debian/patches/debian-packaging/avoid-regenerating-defsincdate-use-shipped-file.patch
@@ -0,0 +1,39 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Mon, 29 Aug 2016 12:34:42 -0400
+Subject: avoid regenerating defsincdate (use shipped file)
+
+upstream ships doc/defsincdate in its tarballs. but doc/Makefile.am
+tries to rewrite doc/defsincdate if it notices that any of the files
+have been modified more recently, and it does so assuming that we're
+running from a git repo.
+
+However, we'd rather ship the documents cleanly without regenerating
+defsincdate -- we don't have a git repo available (debian builds from
+upstream tarballs) and any changes to the texinfo files (e.g. from
+debian/patches/) might result in different dates on the files than we
+expect after they're applied by dpkg or quilt or whatever, which makes
+the datestamp unreproducible.
+---
+ doc/Makefile.am | 9 ---------
+ 1 file changed, 9 deletions(-)
+
+diff --git a/doc/Makefile.am b/doc/Makefile.am
+index 2b882c3..6be571b 100644
+--- a/doc/Makefile.am
++++ b/doc/Makefile.am
+@@ -178,15 +178,6 @@ $(myman_pages) gnupg.7 : yat2m-stamp defs.inc
+
+ dist-hook: defsincdate
+
+-defsincdate: $(gnupg_TEXINFOS)
+- : >defsincdate ; \
+- if test -e $(top_srcdir)/.git; then \
+- (cd $(srcdir) && git log -1 --format='%ct' \
+- -- $(gnupg_TEXINFOS) 2>/dev/null) >>defsincdate; \
+- elif test x"$$SOURCE_DATE_EPOCH" != x; then \
+- echo "$$SOURCE_DATE_EPOCH" >>defsincdate ; \
+- fi
+-
+ defs.inc : defsincdate Makefile mkdefsinc
+ incd="`test -f defsincdate || echo '$(srcdir)/'`defsincdate"; \
+ ./mkdefsinc -C $(srcdir) --date "`cat $$incd 2>/dev/null`" \
diff --git a/debian/patches/dirmngr-Only-use-SKS-pool-CA-for-SKS-pool.patch b/debian/patches/dirmngr-Only-use-SKS-pool-CA-for-SKS-pool.patch
new file mode 100644
index 0000000..6a0e778
--- /dev/null
+++ b/debian/patches/dirmngr-Only-use-SKS-pool-CA-for-SKS-pool.patch
@@ -0,0 +1,29 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Sun, 30 Jun 2019 11:54:35 -0400
+Subject: dirmngr: Only use SKS pool CA for SKS pool
+
+* dirmngr/http.c (http_session_new): when checking whether the
+keyserver is the HKPS pool, check specifically against the pool name,
+as ./configure might have been used to select a different default
+keyserver. It makes no sense to apply Kristian's certificate
+authority to anything other than the literal host
+hkps.pool.sks-keyservers.net.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ dirmngr/http.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/dirmngr/http.c b/dirmngr/http.c
+index 5e3f17c..40160e0 100644
+--- a/dirmngr/http.c
++++ b/dirmngr/http.c
+@@ -768,7 +768,7 @@ http_session_new (http_session_t *r_session,
+
+ is_hkps_pool = (intended_hostname
+ && !ascii_strcasecmp (intended_hostname,
+- get_default_keyserver (1)));
++ "hkps.pool.sks-keyservers.net"));
+
+ /* If we are looking for the hkps pool from sks-keyservers.net,
+ * then forcefully use its dedicated certificate authority. */
diff --git a/debian/patches/dirmngr-idling/dirmngr-Avoid-automatically-checking-upstream-swdb.patch b/debian/patches/dirmngr-idling/dirmngr-Avoid-automatically-checking-upstream-swdb.patch
new file mode 100644
index 0000000..bd68c9c
--- /dev/null
+++ b/debian/patches/dirmngr-idling/dirmngr-Avoid-automatically-checking-upstream-swdb.patch
@@ -0,0 +1,47 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Sun, 20 Nov 2016 23:09:24 -0500
+Subject: dirmngr: Avoid automatically checking upstream swdb.
+
+* dirmngr/dirmngr.c (housekeeping_thread): Avoid automatically
+checking upstream's software database. In Debian, software updates
+should be handled by the distro mechanism, and additional upstream
+checks only confuse the user.
+* doc/dirmngr.texi: document that --allow-version-check does nothing.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ dirmngr/dirmngr.c | 2 --
+ doc/dirmngr.texi | 7 ++++---
+ 2 files changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
+index 89eea4e..f26ed63 100644
+--- a/dirmngr/dirmngr.c
++++ b/dirmngr/dirmngr.c
+@@ -1955,8 +1955,6 @@ housekeeping_thread (void *arg)
+ if (network_activity_seen)
+ {
+ network_activity_seen = 0;
+- if (opt.allow_version_check)
+- dirmngr_load_swdb (&ctrlbuf, 0);
+ workqueue_run_global_tasks (&ctrlbuf, 1);
+ }
+ else
+diff --git a/doc/dirmngr.texi b/doc/dirmngr.texi
+index 843fdbf..84a8d28 100644
+--- a/doc/dirmngr.texi
++++ b/doc/dirmngr.texi
+@@ -291,9 +291,10 @@ Set the size of the queue for pending connections. The default is 64.
+ @item --allow-version-check
+ @opindex allow-version-check
+ Allow Dirmngr to connect to @code{https://versions.gnupg.org} to get
+-the list of current software versions. If this option is enabled
+-the list is retrieved in case the local
+-copy does not exist or is older than 5 to 7 days. See the option
++the list of current software versions.
++On debian-packaged versions, this option does nothing since software
++updates should be handled by the distribution.
++See the option
+ @option{--query-swdb} of the command @command{gpgconf} for more
+ details. Note, that regardless of this option a version check can
+ always be triggered using this command:
diff --git a/debian/patches/dirmngr-idling/dirmngr-Avoid-need-for-hkp-housekeeping.patch b/debian/patches/dirmngr-idling/dirmngr-Avoid-need-for-hkp-housekeeping.patch
new file mode 100644
index 0000000..cbd1695
--- /dev/null
+++ b/debian/patches/dirmngr-idling/dirmngr-Avoid-need-for-hkp-housekeeping.patch
@@ -0,0 +1,230 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Sat, 29 Oct 2016 02:00:50 -0400
+Subject: dirmngr: Avoid need for hkp housekeeping.
+
+* dirmngr/ks-engine-hkp.c (host_is_alive): New function. Test whether
+host is alive and resurrects it if it has been dead long enough.
+(select_random_host, map_host, ks_hkp_mark_host): Use host_is_alive
+instead of testing hostinfo_t->dead directly.
+(ks_hkp_housekeeping): Remove function, no longer needed.
+* dirmngr/dirmngr.c (housekeeping_thread): Remove call to
+ks_hkp_housekeeping.
+
+--
+
+Rather than resurrecting hosts upon scheduled resurrection times, test
+whether hosts should be resurrected as they're inspected for being
+dead. This removes the need for explicit housekeeping, and makes host
+resurrections happen "just in time", rather than being clustered on
+HOUSEKEEPING_INTERVAL seconds.
+
+According to 392e068e9f143d41f6350345619543cbcd47380f,
+dns_stuff_housekeeping only works on Windows, so it also isn't
+necessary in debian, but it remains in place for now.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ dirmngr/dirmngr.c | 3 ---
+ dirmngr/dirmngr.h | 1 -
+ dirmngr/ks-engine-hkp.c | 72 ++++++++++++++++++++++++-------------------------
+ 3 files changed, 35 insertions(+), 41 deletions(-)
+
+diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
+index ae967dd..89eea4e 100644
+--- a/dirmngr/dirmngr.c
++++ b/dirmngr/dirmngr.c
+@@ -1935,12 +1935,10 @@ static void *
+ housekeeping_thread (void *arg)
+ {
+ static int sentinel;
+- time_t curtime;
+ struct server_control_s ctrlbuf;
+
+ (void)arg;
+
+- curtime = gnupg_get_time ();
+ if (sentinel)
+ {
+ log_info ("housekeeping is already going on\n");
+@@ -1954,7 +1952,6 @@ housekeeping_thread (void *arg)
+ dirmngr_init_default_ctrl (&ctrlbuf);
+
+ dns_stuff_housekeeping ();
+- ks_hkp_housekeeping (curtime);
+ if (network_activity_seen)
+ {
+ network_activity_seen = 0;
+diff --git a/dirmngr/dirmngr.h b/dirmngr/dirmngr.h
+index 1b52a1d..4afc19b 100644
+--- a/dirmngr/dirmngr.h
++++ b/dirmngr/dirmngr.h
+@@ -217,7 +217,6 @@ const char* dirmngr_get_current_socket_name (void);
+ int dirmngr_use_tor (void);
+
+ /*-- Various housekeeping functions. --*/
+-void ks_hkp_housekeeping (time_t curtime);
+ void ks_hkp_reload (void);
+
+
+diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
+index d425363..c50681d 100644
+--- a/dirmngr/ks-engine-hkp.c
++++ b/dirmngr/ks-engine-hkp.c
+@@ -218,6 +218,24 @@ host_in_pool_p (hostinfo_t hi, int tblidx)
+ return 0;
+ }
+
++static int
++host_is_alive (hostinfo_t hi, time_t curtime)
++{
++ if (!hi)
++ return 0;
++ if (!hi->dead)
++ return 1;
++ if (!hi->died_at)
++ return 0; /* manually marked dead */
++ if (hi->died_at + RESURRECT_INTERVAL <= curtime
++ || hi->died_at > curtime)
++ {
++ hi->dead = 0;
++ log_info ("resurrected host '%s'", hi->name);
++ return 1;
++ }
++ return 0;
++}
+
+ /* Select a random host. Consult HI->pool which indices into the global
+ hosttable. Returns index into HI->pool or -1 if no host could be
+@@ -228,13 +246,15 @@ select_random_host (hostinfo_t hi)
+ int *tbl = NULL;
+ size_t tblsize = 0;
+ int pidx, idx;
++ time_t curtime;
+
++ curtime = gnupg_get_time ();
+ /* We create a new table so that we randomly select only from
+ currently alive hosts. */
+ for (idx = 0;
+ idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
+ idx++)
+- if (hosttable[pidx] && !hosttable[pidx]->dead)
++ if (hosttable[pidx] && host_is_alive (hosttable[pidx], curtime))
+ {
+ tblsize++;
+ tbl = xtryrealloc(tbl, tblsize * sizeof *tbl);
+@@ -462,6 +482,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
+ int is_pool;
+ int new_hosts = 0;
+ char *cname;
++ time_t curtime;
+
+ *r_host = NULL;
+ if (r_httpflags)
+@@ -501,6 +522,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
+ }
+ else
+ hi = hosttable[idx];
++ curtime = gnupg_get_time ();
+
+ is_pool = hi->pool != NULL;
+
+@@ -607,7 +629,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
+ if (force_reselect)
+ hi->poolidx = -1;
+ else if (hi->poolidx >= 0 && hi->poolidx < hosttable_size
+- && hosttable[hi->poolidx] && hosttable[hi->poolidx]->dead)
++ && hosttable[hi->poolidx] && !host_is_alive (hosttable[hi->poolidx], curtime))
+ hi->poolidx = -1;
+
+ /* Select a host if needed. */
+@@ -665,7 +687,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
+ return gpg_error_from_syserror ();
+ }
+
+- if (hi->dead)
++ if (!host_is_alive (hi, curtime))
+ {
+ log_error ("host '%s' marked as dead\n", hi->name);
+ if (r_httphost)
+@@ -770,7 +792,8 @@ ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
+ {
+ gpg_error_t err = 0;
+ hostinfo_t hi, hi2;
+- int idx, idx2, idx3, n;
++ int idx, idx2, idx3, n, is_alive;
++ time_t curtime;
+
+ if (!name || !*name || !strcmp (name, "localhost"))
+ return 0;
+@@ -779,13 +802,15 @@ ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
+ if (idx == -1)
+ return gpg_error (GPG_ERR_NOT_FOUND);
+
++ curtime = gnupg_get_time ();
+ hi = hosttable[idx];
+- if (alive && hi->dead)
++ is_alive = host_is_alive (hi, curtime);
++ if (alive && !is_alive)
+ {
+ hi->dead = 0;
+ err = ks_printf_help (ctrl, "marking '%s' as alive", name);
+ }
+- else if (!alive && !hi->dead)
++ else if (!alive && is_alive)
+ {
+ hi->dead = 1;
+ hi->died_at = 0; /* Manually set dead. */
+@@ -819,14 +844,15 @@ ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
+
+ hi2 = hosttable[n];
+ if (!hi2)
+- ;
+- else if (alive && hi2->dead)
++ continue;
++ is_alive = host_is_alive (hi2, curtime);
++ if (alive && !is_alive)
+ {
+ hi2->dead = 0;
+ err = ks_printf_help (ctrl, "marking '%s' as alive",
+ hi2->name);
+ }
+- else if (!alive && !hi2->dead)
++ else if (!alive && is_alive)
+ {
+ hi2->dead = 1;
+ hi2->died_at = 0; /* Manually set dead. */
+@@ -1112,34 +1138,6 @@ ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri)
+ }
+
+
+-/* Housekeeping function called from the housekeeping thread. It is
+- used to mark dead hosts alive so that they may be tried again after
+- some time. */
+-void
+-ks_hkp_housekeeping (time_t curtime)
+-{
+- int idx;
+- hostinfo_t hi;
+-
+- for (idx=0; idx < hosttable_size; idx++)
+- {
+- hi = hosttable[idx];
+- if (!hi)
+- continue;
+- if (!hi->dead)
+- continue;
+- if (!hi->died_at)
+- continue; /* Do not resurrect manually shot hosts. */
+- if (hi->died_at + RESURRECT_INTERVAL <= curtime
+- || hi->died_at > curtime)
+- {
+- hi->dead = 0;
+- log_info ("resurrected host '%s'", hi->name);
+- }
+- }
+-}
+-
+-
+ /* Reload (SIGHUP) action for this module. We mark all host alive
+ * even those which have been manually shot. */
+ void
diff --git a/debian/patches/dirmngr-idling/dirmngr-hkp-Avoid-potential-race-condition-when-some.patch b/debian/patches/dirmngr-idling/dirmngr-hkp-Avoid-potential-race-condition-when-some.patch
new file mode 100644
index 0000000..49ebbd4
--- /dev/null
+++ b/debian/patches/dirmngr-idling/dirmngr-hkp-Avoid-potential-race-condition-when-some.patch
@@ -0,0 +1,81 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Sat, 29 Oct 2016 01:25:05 -0400
+Subject: dirmngr: hkp: Avoid potential race condition when some hosts die.
+
+* dirmngr/ks-engine-hkp.c (select_random_host): Use atomic pass
+through the host table instead of risking out-of-bounds write.
+
+--
+
+Multiple threads may write to hosttable[x]->dead while
+select_random_host() is running. For example, a housekeeping thread
+might clear the ->dead bit on some entries, or another connection to
+dirmngr might manually mark a host as alive.
+
+If one or more hosts are resurrected between the two loops over a
+given table in select_random_host(), then the allocation of tbl might
+not be large enough, resulting in a write past the end of tbl on the
+second loop.
+
+This change collapses the two loops into a single loop to avoid this
+discrepancy: each host's "dead" bit is now only checked once.
+
+As Werner points out, this isn't currently strictly necessary, since
+npth will not switch threads unless a blocking system call is made,
+and no blocking system call is made in these two loops.
+
+However, in a subsequent change in this series, we will call a
+function in this loop, and that function may sometimes write(2), or
+call other functions, which may themselves block. Keeping this as a
+single-pass loop avoids the need to keep track of what might block and
+what might not.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ dirmngr/ks-engine-hkp.c | 23 ++++++++++-------------
+ 1 file changed, 10 insertions(+), 13 deletions(-)
+
+diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
+index 14859c7..d425363 100644
+--- a/dirmngr/ks-engine-hkp.c
++++ b/dirmngr/ks-engine-hkp.c
+@@ -225,29 +225,26 @@ host_in_pool_p (hostinfo_t hi, int tblidx)
+ static int
+ select_random_host (hostinfo_t hi)
+ {
+- int *tbl;
+- size_t tblsize;
++ int *tbl = NULL;
++ size_t tblsize = 0;
+ int pidx, idx;
+
+ /* We create a new table so that we randomly select only from
+ currently alive hosts. */
+- for (idx = 0, tblsize = 0;
++ for (idx = 0;
+ idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
+ idx++)
+ if (hosttable[pidx] && !hosttable[pidx]->dead)
+- tblsize++;
++ {
++ tblsize++;
++ tbl = xtryrealloc(tbl, tblsize * sizeof *tbl);
++ if (!tbl)
++ return -1; /* memory allocation failed! */
++ tbl[tblsize-1] = pidx;
++ }
+ if (!tblsize)
+ return -1; /* No hosts. */
+
+- tbl = xtrymalloc (tblsize * sizeof *tbl);
+- if (!tbl)
+- return -1;
+- for (idx = 0, tblsize = 0;
+- idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
+- idx++)
+- if (hosttable[pidx] && !hosttable[pidx]->dead)
+- tbl[tblsize++] = pidx;
+-
+ if (tblsize == 1) /* Save a get_uint_nonce. */
+ pidx = tbl[0];
+ else
diff --git a/debian/patches/from-master/gpg-change-agent-spawn-2019-07-24-v2.patch b/debian/patches/from-master/gpg-change-agent-spawn-2019-07-24-v2.patch
new file mode 100644
index 0000000..849e985
--- /dev/null
+++ b/debian/patches/from-master/gpg-change-agent-spawn-2019-07-24-v2.patch
@@ -0,0 +1,50 @@
+From: NIIBE Yutaka <gniibe@fsij.org>
+Date: Thu, 22 Oct 2020 11:32:00 +0900
+Subject: buildd: sbuild randomly fails to sign changes file despite valid
+ signature keys
+Forwarded: https://dev.gnupg.org/rGb1c56cf9e2bb51abfd47747128bd2a6285ed1623
+
+---
+ common/asshelp.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/common/asshelp.c b/common/asshelp.c
+index d87017e..9f269ab 100644
+--- a/common/asshelp.c
++++ b/common/asshelp.c
+@@ -477,8 +477,18 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
+ if (!(err = lock_spawning (&lock, gnupg_homedir (), "agent", verbose))
+ && assuan_socket_connect (ctx, sockname, 0, 0))
+ {
++#ifdef HAVE_W32_SYSTEM
+ err = gnupg_spawn_process_detached (program? program : agent_program,
+ argv, NULL);
++#else
++ pid_t pid;
++
++ err = gnupg_spawn_process_fd (program? program : agent_program,
++ argv, -1, -1, -1, &pid);
++ if (!err)
++ err = gnupg_wait_process (program? program : agent_program,
++ pid, 1, NULL);
++#endif
+ if (err)
+ log_error ("failed to start agent '%s': %s\n",
+ agent_program, gpg_strerror (err));
+@@ -612,7 +622,16 @@ start_new_dirmngr (assuan_context_t *r_ctx,
+ if (!(err = lock_spawning (&lock, gnupg_homedir (), "dirmngr", verbose))
+ && assuan_socket_connect (ctx, sockname, 0, 0))
+ {
++#ifdef HAVE_W32_SYSTEM
+ err = gnupg_spawn_process_detached (dirmngr_program, argv, NULL);
++#else
++ pid_t pid;
++
++ err = gnupg_spawn_process_fd (dirmngr_program, argv,
++ -1, -1, -1, &pid);
++ if (!err)
++ err = gnupg_wait_process (dirmngr_program, pid, 1, NULL);
++#endif
+ if (err)
+ log_error ("failed to start the dirmngr '%s': %s\n",
+ dirmngr_program, gpg_strerror (err));
diff --git a/debian/patches/from-master/gpg-default-to-3072-bit-keys.patch b/debian/patches/from-master/gpg-default-to-3072-bit-keys.patch
new file mode 100644
index 0000000..54b4292
--- /dev/null
+++ b/debian/patches/from-master/gpg-default-to-3072-bit-keys.patch
@@ -0,0 +1,91 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Thu, 7 Sep 2017 18:41:10 -0400
+Subject: gpg: default to 3072-bit keys.
+
+* agent/command.c (hlp_genkey): update help text to suggest the use of
+3072 bits.
+* doc/wks.texi: Make example match default generation.
+* g10/keygen.c (gen_elg): update default from 2048 to 3072.
+* g10/keyid.c (pubkey_string): update comment so that first example
+is the default 3072-bit RSA.
+
+--
+
+3072-bit RSA is widely considered to be 128-bit-equivalent security.
+This is a sensible default in 2017.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+
+(cherry picked from commit 909fbca19678e6e36968607e8a2348381da39d8c)
+---
+ agent/command.c | 2 +-
+ doc/wks.texi | 4 ++--
+ g10/keygen.c | 2 +-
+ g10/keyid.c | 4 ++--
+ 4 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/agent/command.c b/agent/command.c
+index 8642498..f94e770 100644
+--- a/agent/command.c
++++ b/agent/command.c
+@@ -843,7 +843,7 @@ static const char hlp_genkey[] =
+ "\n"
+ " C: GENKEY\n"
+ " S: INQUIRE KEYPARAM\n"
+- " C: D (genkey (rsa (nbits 2048)))\n"
++ " C: D (genkey (rsa (nbits 3072)))\n"
+ " C: END\n"
+ " S: D (public-key\n"
+ " S: D (rsa (n 326487324683264) (e 10001)))\n"
+diff --git a/doc/wks.texi b/doc/wks.texi
+index 119e31c..ae6c310 100644
+--- a/doc/wks.texi
++++ b/doc/wks.texi
+@@ -412,10 +412,10 @@ the submission address:
+ The output of the last command looks similar to this:
+
+ @example
+- sec rsa2048 2016-08-30 [SC]
++ sec rsa3072 2016-08-30 [SC]
+ C0FCF8642D830C53246211400346653590B3795B
+ uid [ultimate] key-submission@@example.net
+- ssb rsa2048 2016-08-30 [E]
++ ssb rsa3072 2016-08-30 [E]
+ @end example
+
+ Take the fingerprint from that output and manually publish the key:
+diff --git a/g10/keygen.c b/g10/keygen.c
+index d50acf8..79d4579 100644
+--- a/g10/keygen.c
++++ b/g10/keygen.c
+@@ -1436,7 +1436,7 @@ gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
+
+ if (nbits < 1024)
+ {
+- nbits = 2048;
++ nbits = 3072;
+ log_info (_("keysize invalid; using %u bits\n"), nbits );
+ }
+ else if (nbits > 4096)
+diff --git a/g10/keyid.c b/g10/keyid.c
+index 69d85da..2987287 100644
+--- a/g10/keyid.c
++++ b/g10/keyid.c
+@@ -73,7 +73,7 @@ pubkey_letter( int algo )
+ is copied to the supplied buffer up a length of BUFSIZE-1.
+ Examples for the output are:
+
+- "rsa2048" - RSA with 2048 bit
++ "rsa3072" - RSA with 3072 bit
+ "elg1024" - Elgamal with 1024 bit
+ "ed25519" - ECC using the curve Ed25519.
+ "E_1.2.3.4" - ECC using the unsupported curve with OID "1.2.3.4".
+@@ -83,7 +83,7 @@ pubkey_letter( int algo )
+ If the option --legacy-list-mode is active, the output use the
+ legacy format:
+
+- "2048R" - RSA with 2048 bit
++ "3072R" - RSA with 3072 bit
+ "1024g" - Elgamal with 1024 bit
+ "256E" - ECDSA using a curve with 256 bit
+
diff --git a/debian/patches/from-master/gpg-default-to-AES-256.patch b/debian/patches/from-master/gpg-default-to-AES-256.patch
new file mode 100644
index 0000000..d131f6a
--- /dev/null
+++ b/debian/patches/from-master/gpg-default-to-AES-256.patch
@@ -0,0 +1,35 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Thu, 7 Sep 2017 19:04:00 -0400
+Subject: gpg: default to AES-256.
+
+* g10/main.h (DEFAULT_CIPHER_ALGO): Prefer AES256 by default.
+
+--
+
+It's 2017, and pretty much everyone has AES-256 available. Symmetric
+crypto is also rarely the bottleneck (asymmetric crypto is much more
+expensive). AES-256 provides some level of protection against
+large-scale decryption efforts, and longer key lengths provide a hedge
+against unforseen cryptanalysis.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+(cherry picked from commit 73ff075204df09db5248170a049f06498cdbb7aa)
+---
+ g10/main.h | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/g10/main.h b/g10/main.h
+index 68360e2..1983e42 100644
+--- a/g10/main.h
++++ b/g10/main.h
+@@ -31,7 +31,9 @@
+ (i.e. uncompressed) rather than 1 (zip). However, the real world
+ issues of speed and size come into play here. */
+
+-#if GPG_USE_AES128
++#if GPG_USE_AES256
++# define DEFAULT_CIPHER_ALGO CIPHER_ALGO_AES256
++#elif GPG_USE_AES128
+ # define DEFAULT_CIPHER_ALGO CIPHER_ALGO_AES
+ #elif GPG_USE_CAST5
+ # define DEFAULT_CIPHER_ALGO CIPHER_ALGO_CAST5
diff --git a/debian/patches/gpg-agent-idling/agent-Allow-threads-to-interrupt-main-select-loop-wi.patch b/debian/patches/gpg-agent-idling/agent-Allow-threads-to-interrupt-main-select-loop-wi.patch
new file mode 100644
index 0000000..f0f1ef6
--- /dev/null
+++ b/debian/patches/gpg-agent-idling/agent-Allow-threads-to-interrupt-main-select-loop-wi.patch
@@ -0,0 +1,84 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Tue, 1 Nov 2016 00:45:23 -0400
+Subject: agent: Allow threads to interrupt main select loop with SIGCONT.
+
+* agent/gpg-agent.c (interrupt_main_thread_loop): New function on
+non-windows platforms, allows other threads to interrupt the main loop
+if there's something that the main loop might be interested in.
+
+--
+
+For example, the main loop might be interested in changes in program
+state that affect the timers it expects to see.
+
+I don't know how to do this on Windows platforms, but i welcome any
+proposed improvements.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ agent/agent.h | 1 +
+ agent/gpg-agent.c | 16 ++++++++++++++++
+ 2 files changed, 17 insertions(+)
+
+diff --git a/agent/agent.h b/agent/agent.h
+index fb46412..4abc6ed 100644
+--- a/agent/agent.h
++++ b/agent/agent.h
+@@ -375,6 +375,7 @@ void *get_agent_scd_notify_event (void);
+ #endif
+ void agent_sighup_action (void);
+ int map_pk_openpgp_to_gcry (int openpgp_algo);
++void interrupt_main_thread_loop (void);
+
+ /*-- command.c --*/
+ gpg_error_t agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid,
+diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
+index 69705ed..752552c 100644
+--- a/agent/gpg-agent.c
++++ b/agent/gpg-agent.c
+@@ -430,6 +430,9 @@ static int have_homedir_inotify;
+ * works reliable. */
+ static int reliable_homedir_inotify;
+
++/* Record the pid of the main thread, for easier signalling */
++static pid_t main_thread_pid = (pid_t)(-1);
++
+ /* Number of active connections. */
+ static int active_connections;
+
+@@ -2458,6 +2461,10 @@ handle_signal (int signo)
+ agent_sigusr2_action ();
+ break;
+
++ /* nothing to do here, just take an extra cycle on the select loop */
++ case SIGCONT:
++ break;
++
+ case SIGTERM:
+ if (!shutdown_pending)
+ log_info ("SIGTERM received - shutting down ...\n");
+@@ -2796,6 +2803,13 @@ start_connection_thread_ssh (void *arg)
+ }
+
+
++void interrupt_main_thread_loop (void)
++{
++#ifndef HAVE_W32_SYSTEM
++ kill (main_thread_pid, SIGCONT);
++#endif
++}
++
+ /* helper function for readability: test whether a given struct
+ timespec is set to all-zeros */
+ static inline int
+@@ -2865,8 +2879,10 @@ handle_connections (gnupg_fd_t listen_fd,
+ npth_sigev_add (SIGUSR1);
+ npth_sigev_add (SIGUSR2);
+ npth_sigev_add (SIGINT);
++ npth_sigev_add (SIGCONT);
+ npth_sigev_add (SIGTERM);
+ npth_sigev_fini ();
++ main_thread_pid = getpid ();
+ #else
+ # ifdef HAVE_W32CE_SYSTEM
+ /* Use a dummy event. */
diff --git a/debian/patches/gpg-agent-idling/agent-Avoid-scheduled-checks-on-socket-when-inotify-.patch b/debian/patches/gpg-agent-idling/agent-Avoid-scheduled-checks-on-socket-when-inotify-.patch
new file mode 100644
index 0000000..3cef203
--- /dev/null
+++ b/debian/patches/gpg-agent-idling/agent-Avoid-scheduled-checks-on-socket-when-inotify-.patch
@@ -0,0 +1,26 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Tue, 1 Nov 2016 00:57:44 -0400
+Subject: agent: Avoid scheduled checks on socket when inotify is working.
+
+* agent/gpg-agent.c (handle_connections): When inotify is working, we
+do not need to schedule a timer to evaluate whether we control our own
+socket or not.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ agent/gpg-agent.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
+index eff82ca..3ae77c6 100644
+--- a/agent/gpg-agent.c
++++ b/agent/gpg-agent.c
+@@ -3032,6 +3032,8 @@ handle_connections (gnupg_fd_t listen_fd,
+
+ /* avoid a fine-grained timer if we don't need one: */
+ timertbl[0].interval.tv_sec = need_tick () ? TIMERTICK_INTERVAL : 0;
++ /* avoid waking up to check sockets if we can count on inotify */
++ timertbl[1].interval.tv_sec = (sock_inotify_fd == -1) ? CHECK_OWN_SOCKET_INTERVAL : 0;
+
+ /* loop through all timers, fire any registered functions, and
+ plan next timer to trigger */
diff --git a/debian/patches/gpg-agent-idling/agent-Avoid-tight-timer-tick-when-possible.patch b/debian/patches/gpg-agent-idling/agent-Avoid-tight-timer-tick-when-possible.patch
new file mode 100644
index 0000000..3900cf4
--- /dev/null
+++ b/debian/patches/gpg-agent-idling/agent-Avoid-tight-timer-tick-when-possible.patch
@@ -0,0 +1,101 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Tue, 1 Nov 2016 00:14:10 -0400
+Subject: agent: Avoid tight timer tick when possible.
+
+* agent/gpg-agent.c (need_tick): Evaluate whether the short-phase
+handle_tick() is needed.
+(handle_connections): On each cycle of the select loop, adjust whether
+we should call handle_tick() or not.
+(start_connection_thread_ssh, do_start_connection_thread): Signal the
+main loop when the child terminates.
+* agent/call-scd.c (start_scd): Call interrupt_main_thread_loop() once
+the scdaemon thread context has started up.
+
+--
+
+With this change, an idle gpg-agent that has no scdaemon running only
+wakes up once a minute (to check_own_socket).
+
+Thanks to Ian Jackson and NIIBE Yutaka who helped me improve some of
+the blocking and corner cases.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ agent/call-scd.c | 2 ++
+ agent/gpg-agent.c | 29 +++++++++++++++++++++++++++--
+ 2 files changed, 29 insertions(+), 2 deletions(-)
+
+diff --git a/agent/call-scd.c b/agent/call-scd.c
+index 6438693..ee69bb4 100644
+--- a/agent/call-scd.c
++++ b/agent/call-scd.c
+@@ -414,6 +414,8 @@ start_scd (ctrl_t ctrl)
+
+ primary_scd_ctx = ctx;
+ primary_scd_ctx_reusable = 0;
++ /* notify the main loop that something has changed */
++ interrupt_main_thread_loop ();
+
+ leave:
+ xfree (abs_homedir);
+diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
+index 752552c..eff82ca 100644
+--- a/agent/gpg-agent.c
++++ b/agent/gpg-agent.c
+@@ -2362,6 +2362,26 @@ create_directories (void)
+ }
+
+
++static int
++need_tick (void)
++{
++#ifdef HAVE_W32_SYSTEM
++ /* We do not know how to interrupt the select loop on Windows, so we
++ always need a short tick there. */
++ return 1;
++#else
++ /* if we were invoked like "gpg-agent cmd arg1 arg2" then we need to
++ watch our parent. */
++ if (parent_pid != (pid_t)(-1))
++ return 1;
++ /* if scdaemon is running, we need to check that it's alive */
++ if (agent_scd_check_running ())
++ return 1;
++ /* otherwise, nothing fine-grained to do. */
++ return 0;
++#endif /*HAVE_W32_SYSTEM*/
++}
++
+
+ /* This is the worker for the ticker. It is called every few seconds
+ and may only do fast operations. */
+@@ -2718,7 +2738,8 @@ do_start_connection_thread (ctrl_t ctrl)
+
+ agent_deinit_default_ctrl (ctrl);
+ xfree (ctrl);
+- active_connections--;
++ if (--active_connections == 0)
++ interrupt_main_thread_loop();
+ return NULL;
+ }
+
+@@ -2798,7 +2819,8 @@ start_connection_thread_ssh (void *arg)
+
+ agent_deinit_default_ctrl (ctrl);
+ xfree (ctrl);
+- active_connections--;
++ if (--active_connections == 0)
++ interrupt_main_thread_loop();
+ return NULL;
+ }
+
+@@ -3008,6 +3030,9 @@ handle_connections (gnupg_fd_t listen_fd,
+ thus a simple assignment is fine to copy the entire set. */
+ read_fdset = fdset;
+
++ /* avoid a fine-grained timer if we don't need one: */
++ timertbl[0].interval.tv_sec = need_tick () ? TIMERTICK_INTERVAL : 0;
++
+ /* loop through all timers, fire any registered functions, and
+ plan next timer to trigger */
+ npth_clock_gettime (&curtime);
diff --git a/debian/patches/gpg-agent-idling/agent-Create-framework-of-scheduled-timers.patch b/debian/patches/gpg-agent-idling/agent-Create-framework-of-scheduled-timers.patch
new file mode 100644
index 0000000..29bbd54
--- /dev/null
+++ b/debian/patches/gpg-agent-idling/agent-Create-framework-of-scheduled-timers.patch
@@ -0,0 +1,191 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Mon, 31 Oct 2016 21:27:36 -0400
+Subject: agent: Create framework of scheduled timers.
+
+agent/gpg-agent.c (handle_tick): Remove intermittent call to
+check_own_socket.
+(tv_is_set): Add inline helper function for readability.
+(handle_connections) Create general table of pending scheduled
+timeouts.
+
+--
+
+handle_tick() does fine-grained, rapid activity. check_own_socket()
+is supposed to happen at a different interval.
+
+Mixing the two of them makes it a requirement that one interval be a
+multiple of the other, which isn't ideal if there are different delay
+strategies that we might want in the future.
+
+Creating an extensible regular timer framework in handle_connections
+should make it possible to have any number of cadenced timers fire
+regularly, without requiring that they happen in cadences related to
+each other.
+
+It should also make it possible to dynamically change the cadence of
+any regularly-scheduled timeout.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ agent/gpg-agent.c | 84 +++++++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 57 insertions(+), 27 deletions(-)
+
+diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
+index 5afcf11..69705ed 100644
+--- a/agent/gpg-agent.c
++++ b/agent/gpg-agent.c
+@@ -2365,12 +2365,8 @@ create_directories (void)
+ static void
+ handle_tick (void)
+ {
+- static time_t last_minute;
+ struct stat statbuf;
+
+- if (!last_minute)
+- last_minute = time (NULL);
+-
+ /* Check whether the scdaemon has died and cleanup in this case. */
+ agent_scd_check_aliveness ();
+
+@@ -2390,15 +2386,6 @@ handle_tick (void)
+ }
+ #endif /*HAVE_W32_SYSTEM*/
+
+- /* Code to be run from time to time. */
+-#if CHECK_OWN_SOCKET_INTERVAL > 0
+- if (last_minute + CHECK_OWN_SOCKET_INTERVAL <= time (NULL))
+- {
+- check_own_socket ();
+- last_minute = time (NULL);
+- }
+-#endif
+-
+ /* Need to check for expired cache entries. */
+ agent_cache_housekeeping ();
+
+@@ -2809,6 +2796,15 @@ start_connection_thread_ssh (void *arg)
+ }
+
+
++/* helper function for readability: test whether a given struct
++ timespec is set to all-zeros */
++static inline int
++tv_is_set (struct timespec tv)
++{
++ return tv.tv_sec || tv.tv_nsec;
++}
++
++
+ /* Connection handler loop. Wait for connection requests and spawn a
+ thread after accepting a connection. */
+ static void
+@@ -2826,9 +2822,11 @@ handle_connections (gnupg_fd_t listen_fd,
+ gnupg_fd_t fd;
+ int nfd;
+ int saved_errno;
++ int idx;
+ struct timespec abstime;
+ struct timespec curtime;
+ struct timespec timeout;
++ struct timespec *select_timeout;
+ #ifdef HAVE_W32_SYSTEM
+ HANDLE events[2];
+ unsigned int events_set;
+@@ -2845,6 +2843,14 @@ handle_connections (gnupg_fd_t listen_fd,
+ { "browser", start_connection_thread_browser },
+ { "ssh", start_connection_thread_ssh }
+ };
++ struct {
++ struct timespec interval;
++ void (*func) (void);
++ struct timespec next;
++ } timertbl[] = {
++ { { TIMERTICK_INTERVAL, 0 }, handle_tick },
++ { { CHECK_OWN_SOCKET_INTERVAL, 0 }, check_own_socket }
++ };
+
+
+ ret = npth_attr_init(&tattr);
+@@ -2952,9 +2958,6 @@ handle_connections (gnupg_fd_t listen_fd,
+ listentbl[2].l_fd = listen_fd_browser;
+ listentbl[3].l_fd = listen_fd_ssh;
+
+- npth_clock_gettime (&abstime);
+- abstime.tv_sec += TIMERTICK_INTERVAL;
+-
+ for (;;)
+ {
+ /* Shutdown test. */
+@@ -2989,18 +2992,46 @@ handle_connections (gnupg_fd_t listen_fd,
+ thus a simple assignment is fine to copy the entire set. */
+ read_fdset = fdset;
+
++ /* loop through all timers, fire any registered functions, and
++ plan next timer to trigger */
+ npth_clock_gettime (&curtime);
+- if (!(npth_timercmp (&curtime, &abstime, <)))
+- {
+- /* Timeout. */
+- handle_tick ();
+- npth_clock_gettime (&abstime);
+- abstime.tv_sec += TIMERTICK_INTERVAL;
+- }
+- npth_timersub (&abstime, &curtime, &timeout);
++ abstime.tv_sec = abstime.tv_nsec = 0;
++ for (idx=0; idx < DIM(timertbl); idx++)
++ {
++ /* schedule any unscheduled timers */
++ if ((!tv_is_set (timertbl[idx].next)) && tv_is_set (timertbl[idx].interval))
++ npth_timeradd (&timertbl[idx].interval, &curtime, &timertbl[idx].next);
++ /* if a timer is due, fire it ... */
++ if (tv_is_set (timertbl[idx].next))
++ {
++ if (!(npth_timercmp (&curtime, &timertbl[idx].next, <)))
++ {
++ timertbl[idx].func ();
++ npth_clock_gettime (&curtime);
++ /* ...and reschedule it, if desired: */
++ if (tv_is_set (timertbl[idx].interval))
++ npth_timeradd (&timertbl[idx].interval, &curtime, &timertbl[idx].next);
++ else
++ timertbl[idx].next.tv_sec = timertbl[idx].next.tv_nsec = 0;
++ }
++ }
++ /* accumulate next timer to come due in abstime: */
++ if (tv_is_set (timertbl[idx].next) &&
++ ((!tv_is_set (abstime)) ||
++ (npth_timercmp (&abstime, &timertbl[idx].next, >))))
++ abstime = timertbl[idx].next;
++ }
++ /* choose a timeout for the select loop: */
++ if (tv_is_set (abstime))
++ {
++ npth_timersub (&abstime, &curtime, &timeout);
++ select_timeout = &timeout;
++ }
++ else
++ select_timeout = NULL;
+
+ #ifndef HAVE_W32_SYSTEM
+- ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, &timeout,
++ ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, select_timeout,
+ npth_sigev_sigmask ());
+ saved_errno = errno;
+
+@@ -3010,7 +3041,7 @@ handle_connections (gnupg_fd_t listen_fd,
+ handle_signal (signo);
+ }
+ #else
+- ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, &timeout,
++ ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, select_timeout,
+ events, &events_set);
+ saved_errno = errno;
+
+@@ -3055,7 +3086,6 @@ handle_connections (gnupg_fd_t listen_fd,
+
+ if (!shutdown_pending)
+ {
+- int idx;
+ ctrl_t ctrl;
+ npth_t thread;
+
diff --git a/debian/patches/gpg-drop-import-clean-from-default-keyserver-import-optio.patch b/debian/patches/gpg-drop-import-clean-from-default-keyserver-import-optio.patch
new file mode 100644
index 0000000..6fa2283
--- /dev/null
+++ b/debian/patches/gpg-drop-import-clean-from-default-keyserver-import-optio.patch
@@ -0,0 +1,49 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Mon, 15 Jul 2019 16:24:35 -0400
+Subject: gpg: drop import-clean from default keyserver import options
+
+* g10/gpg.c (main): drop IMPORT_CLEAN from the
+default opt.keyserver_options.import_options
+* doc/gpg.texi: reflect this change in the documentation
+
+Given that SELF_SIGS_ONLY is already set, it's not clear what
+additional benefit IMPORT_CLEAN provides. Furthermore, IMPORT_CLEAN
+means that receiving an OpenPGP certificate from a keyserver will
+potentially delete data that is otherwise held in the local keyring,
+which is surprising to users who expect retrieval from the keyservers
+to be purely additive.
+
+GnuPG-Bug-Id: 4628
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ doc/gpg.texi | 2 +-
+ g10/gpg.c | 3 +--
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/doc/gpg.texi b/doc/gpg.texi
+index 7b603d7..104318a 100644
+--- a/doc/gpg.texi
++++ b/doc/gpg.texi
+@@ -1982,7 +1982,7 @@ are available for all keyserver types, some common options are:
+
+ @end table
+
+-The default list of options is: "self-sigs-only, import-clean,
++The default list of options is: "self-sigs-only,
+ repair-keys, repair-pks-subkey-bug, export-attributes,
+ honor-pka-record".
+
+diff --git a/g10/gpg.c b/g10/gpg.c
+index 6b44cfb..caa0487 100644
+--- a/g10/gpg.c
++++ b/g10/gpg.c
+@@ -2348,8 +2348,7 @@ main (int argc, char **argv)
+ opt.export_options = EXPORT_ATTRIBUTES;
+ opt.keyserver_options.import_options = (IMPORT_REPAIR_KEYS
+ | IMPORT_REPAIR_PKS_SUBKEY_BUG
+- | IMPORT_SELF_SIGS_ONLY
+- | IMPORT_CLEAN);
++ | IMPORT_SELF_SIGS_ONLY);
+ opt.keyserver_options.export_options = EXPORT_ATTRIBUTES;
+ opt.keyserver_options.options = KEYSERVER_HONOR_PKA_RECORD;
+ opt.verify_options = (LIST_SHOW_UID_VALIDITY
diff --git a/debian/patches/import-merge-without-userid/gpg-accept-subkeys-with-a-good-revocation-but-no-self-sig.patch b/debian/patches/import-merge-without-userid/gpg-accept-subkeys-with-a-good-revocation-but-no-self-sig.patch
new file mode 100644
index 0000000..e448a0a
--- /dev/null
+++ b/debian/patches/import-merge-without-userid/gpg-accept-subkeys-with-a-good-revocation-but-no-self-sig.patch
@@ -0,0 +1,32 @@
+From: Vincent Breitmoser <look@my.amazin.horse>
+Date: Thu, 13 Jun 2019 21:27:43 +0200
+Subject: gpg: accept subkeys with a good revocation but no self-sig during
+ import
+
+* g10/import.c (chk_self_sigs): Set the NODE_GOOD_SELFSIG flag when we
+encounter a valid revocation signature. This allows import of subkey
+revocation signatures, even in the absence of a corresponding subkey
+binding signature.
+
+--
+
+This fixes the remaining test in import-incomplete.scm.
+
+GnuPG-Bug-id: 4393
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ g10/import.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/g10/import.c b/g10/import.c
+index 79104dc..20f4af5 100644
+--- a/g10/import.c
++++ b/g10/import.c
+@@ -3665,6 +3665,7 @@ chk_self_sigs (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid, int *non_self)
+ /* It's valid, so is it newer? */
+ if (sig->timestamp >= rsdate)
+ {
++ knode->flag |= NODE_GOOD_SELFSIG; /* Subkey is valid. */
+ if (rsnode)
+ {
+ /* Delete the last revocation sig since
diff --git a/debian/patches/import-merge-without-userid/gpg-allow-import-of-previously-known-keys-even-without-UI.patch b/debian/patches/import-merge-without-userid/gpg-allow-import-of-previously-known-keys-even-without-UI.patch
new file mode 100644
index 0000000..fb93748
--- /dev/null
+++ b/debian/patches/import-merge-without-userid/gpg-allow-import-of-previously-known-keys-even-without-UI.patch
@@ -0,0 +1,106 @@
+From: Vincent Breitmoser <look@my.amazin.horse>
+Date: Thu, 13 Jun 2019 21:27:42 +0200
+Subject: gpg: allow import of previously known keys, even without UIDs
+
+* g10/import.c (import_one): Accept an incoming OpenPGP certificate that
+has no user id, as long as we already have a local variant of the cert
+that matches the primary key.
+
+--
+
+This fixes two of the three broken tests in import-incomplete.scm.
+
+GnuPG-Bug-id: 4393
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ g10/import.c | 44 +++++++++++---------------------------------
+ 1 file changed, 11 insertions(+), 33 deletions(-)
+
+diff --git a/g10/import.c b/g10/import.c
+index c8692e2..79104dc 100644
+--- a/g10/import.c
++++ b/g10/import.c
+@@ -1843,7 +1843,6 @@ import_one_real (ctrl_t ctrl,
+ size_t an;
+ char pkstrbuf[PUBKEY_STRING_SIZE];
+ int merge_keys_done = 0;
+- int any_filter = 0;
+ KEYDB_HANDLE hd = NULL;
+
+ if (r_valid)
+@@ -1880,14 +1879,6 @@ import_one_real (ctrl_t ctrl,
+ log_printf ("\n");
+ }
+
+-
+- if (!uidnode )
+- {
+- if (!silent)
+- log_error( _("key %s: no user ID\n"), keystr_from_pk(pk));
+- return 0;
+- }
+-
+ if (screener && screener (keyblock, screener_arg))
+ {
+ log_error (_("key %s: %s\n"), keystr_from_pk (pk),
+@@ -1962,17 +1953,10 @@ import_one_real (ctrl_t ctrl,
+ }
+ }
+
+- if (!delete_inv_parts (ctrl, keyblock, keyid, options ) )
+- {
+- if (!silent)
+- {
+- log_error( _("key %s: no valid user IDs\n"), keystr_from_pk(pk));
+- if (!opt.quiet )
+- log_info(_("this may be caused by a missing self-signature\n"));
+- }
+- stats->no_user_id++;
+- return 0;
+- }
++ /* Delete invalid parts, and note if we have any valid ones left.
++ * We will later abort import if this key is new but contains
++ * no valid uids. */
++ delete_inv_parts (ctrl, keyblock, keyid, options);
+
+ /* Get rid of deleted nodes. */
+ commit_kbnode (&keyblock);
+@@ -1982,24 +1966,11 @@ import_one_real (ctrl_t ctrl,
+ {
+ apply_keep_uid_filter (ctrl, keyblock, import_filter.keep_uid);
+ commit_kbnode (&keyblock);
+- any_filter = 1;
+ }
+ if (import_filter.drop_sig)
+ {
+ apply_drop_sig_filter (ctrl, keyblock, import_filter.drop_sig);
+ commit_kbnode (&keyblock);
+- any_filter = 1;
+- }
+-
+- /* If we ran any filter we need to check that at least one user id
+- * is left in the keyring. Note that we do not use log_error in
+- * this case. */
+- if (any_filter && !any_uid_left (keyblock))
+- {
+- if (!opt.quiet )
+- log_info ( _("key %s: no valid user IDs\n"), keystr_from_pk (pk));
+- stats->no_user_id++;
+- return 0;
+ }
+
+ /* The keyblock is valid and ready for real import. */
+@@ -2057,6 +2028,13 @@ import_one_real (ctrl_t ctrl,
+ err = 0;
+ stats->skipped_new_keys++;
+ }
++ else if (err && !any_uid_left (keyblock))
++ {
++ if (!silent)
++ log_info( _("key %s: new key but contains no user ID - skipped\n"), keystr(keyid));
++ err = 0;
++ stats->no_user_id++;
++ }
+ else if (err) /* Insert this key. */
+ {
+ /* Note: ERR can only be NO_PUBKEY or UNUSABLE_PUBKEY. */
diff --git a/debian/patches/import-merge-without-userid/tests-add-test-cases-for-import-without-uid.patch b/debian/patches/import-merge-without-userid/tests-add-test-cases-for-import-without-uid.patch
new file mode 100644
index 0000000..52ca688
--- /dev/null
+++ b/debian/patches/import-merge-without-userid/tests-add-test-cases-for-import-without-uid.patch
@@ -0,0 +1,201 @@
+From: Vincent Breitmoser <look@my.amazin.horse>
+Date: Thu, 13 Jun 2019 21:27:41 +0200
+Subject: tests: add test cases for import without uid
+
+This commit adds a test case that does the following, in order:
+- Import of a primary key plus user id
+- Check that import of a subkey works, without a user id present in the
+imported key
+- Check that import of a subkey revocation works, without a user id or
+subkey binding signature present in the imported key
+- Check that import of a primary key revocation works, without a user id
+present in the imported key
+
+--
+
+Note that this test currently fails. The following changesets will
+fix gpg so that the tests pass.
+
+GnuPG-Bug-id: 4393
+Signed-Off-By: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ tests/openpgp/Makefile.am | 1 +
+ tests/openpgp/import-incomplete.scm | 68 ++++++++++++++++++++++
+ .../import-incomplete/primary+revocation.asc | 9 +++
+ .../primary+subkey+sub-revocation.asc | 10 ++++
+ .../import-incomplete/primary+subkey+sub-sig.asc | 10 ++++
+ .../openpgp/import-incomplete/primary+uid-sig.asc | 10 ++++
+ tests/openpgp/import-incomplete/primary+uid.asc | 10 ++++
+ 7 files changed, 118 insertions(+)
+ create mode 100755 tests/openpgp/import-incomplete.scm
+ create mode 100644 tests/openpgp/import-incomplete/primary+revocation.asc
+ create mode 100644 tests/openpgp/import-incomplete/primary+subkey+sub-revocation.asc
+ create mode 100644 tests/openpgp/import-incomplete/primary+subkey+sub-sig.asc
+ create mode 100644 tests/openpgp/import-incomplete/primary+uid-sig.asc
+ create mode 100644 tests/openpgp/import-incomplete/primary+uid.asc
+
+diff --git a/tests/openpgp/Makefile.am b/tests/openpgp/Makefile.am
+index 59f39e2..3b8b699 100644
+--- a/tests/openpgp/Makefile.am
++++ b/tests/openpgp/Makefile.am
+@@ -78,6 +78,7 @@ XTESTS = \
+ gpgv-forged-keyring.scm \
+ armor.scm \
+ import.scm \
++ import-incomplete.scm \
+ import-revocation-certificate.scm \
+ ecc.scm \
+ 4gb-packet.scm \
+diff --git a/tests/openpgp/import-incomplete.scm b/tests/openpgp/import-incomplete.scm
+new file mode 100755
+index 0000000..727a027
+--- /dev/null
++++ b/tests/openpgp/import-incomplete.scm
+@@ -0,0 +1,68 @@
++#!/usr/bin/env gpgscm
++
++;; Copyright (C) 2016 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 (in-srcdir "tests" "openpgp" "defs.scm"))
++(setup-environment)
++
++(call-check `(,(tool 'gpg) --import ,(in-srcdir "tests" "openpgp" "import-incomplete" "primary+uid.asc")))
++
++(info "Test import of new subkey, from a certificate without uid")
++(define keyid "573EA710367356BB")
++(call-check `(,(tool 'gpg) --import ,(in-srcdir "tests" "openpgp" "import-incomplete" "primary+subkey+sub-sig.asc")))
++(tr:do
++ (tr:pipe-do
++ (pipe:gpg `(--list-keys --with-colons ,keyid)))
++ (tr:call-with-content
++ (lambda (c)
++ ;; XXX we do not have a regexp library
++ (unless (any (lambda (line)
++ (and (string-prefix? line "sub:")
++ (string-contains? line "573EA710367356BB")))
++ (string-split-newlines c))
++ (exit 1)))))
++
++(info "Test import of a subkey revocation, from a certificate without uid")
++(define keyid "573EA710367356BB")
++(call-check `(,(tool 'gpg) --import ,(in-srcdir "tests" "openpgp" "import-incomplete" "primary+subkey+sub-revocation.asc")))
++(tr:do
++ (tr:pipe-do
++ (pipe:gpg `(--list-keys --with-colons ,keyid)))
++ (tr:call-with-content
++ (lambda (c)
++ ;; XXX we do not have a regexp library
++ (unless (any (lambda (line)
++ (and (string-prefix? line "sub:r:")
++ (string-contains? line "573EA710367356BB")))
++ (string-split-newlines c))
++ (exit 1)))))
++
++(info "Test import of revocation, from a certificate without uid")
++(call-check `(,(tool 'gpg) --import ,(in-srcdir "tests" "openpgp" "import-incomplete" "primary+revocation.asc")))
++(tr:do
++ (tr:pipe-do
++ (pipe:gpg `(--list-keys --with-colons ,keyid)))
++ (tr:call-with-content
++ (lambda (c)
++ ;; XXX we do not have a regexp library
++ (unless (any (lambda (line)
++ (and (string-prefix? line "pub:r:")
++ (string-contains? line "0843DA969AA8DAFB")))
++ (string-split-newlines c))
++ (exit 1)))))
++
+diff --git a/tests/openpgp/import-incomplete/primary+revocation.asc b/tests/openpgp/import-incomplete/primary+revocation.asc
+new file mode 100644
+index 0000000..6b7b608
+--- /dev/null
++++ b/tests/openpgp/import-incomplete/primary+revocation.asc
+@@ -0,0 +1,9 @@
++-----BEGIN PGP PUBLIC KEY BLOCK-----
++Comment: [E] primary key, revocation signature over primary (no user ID)
++
++mDMEXNmUGRYJKwYBBAHaRw8BAQdA75R8VlchvmEd2Iz/8l07RoKUaUPDB71Ao1zZ
++631VAN2IeAQgFggAIBYhBLRpj5W82H/gSMzKKQhD2paaqNr7BQJc2ZQZAh0AAAoJ
++EAhD2paaqNr7qAwA/2jBUpnN0BxwRO/4CrxvrLIsL+C9aSXJUOTv8XkP4lvtAQD3
++XsDFfFNgEueiTfF7HtOGt5LPmRqVvUpQSMVgJJW6CQ==
++=tM90
++-----END PGP PUBLIC KEY BLOCK-----
+diff --git a/tests/openpgp/import-incomplete/primary+subkey+sub-revocation.asc b/tests/openpgp/import-incomplete/primary+subkey+sub-revocation.asc
+new file mode 100644
+index 0000000..83a51a5
+--- /dev/null
++++ b/tests/openpgp/import-incomplete/primary+subkey+sub-revocation.asc
+@@ -0,0 +1,10 @@
++-----BEGIN PGP PUBLIC KEY BLOCK-----
++Comment: [D] primary key, subkey, subkey revocation (no user ID)
++
++mDMEXNmUGRYJKwYBBAHaRw8BAQdA75R8VlchvmEd2Iz/8l07RoKUaUPDB71Ao1zZ
++631VAN24OARc2ZQhEgorBgEEAZdVAQUBAQdABsd5ha0AWXdXcSmfeiWIfrNcGqQK
++j++lwwWDAOlkVicDAQgHiHgEKBYIACAWIQS0aY+VvNh/4EjMyikIQ9qWmqja+wUC
++XNmnkAIdAgAKCRAIQ9qWmqja+ylaAQDmIKf86BJEq4OpDqU+V9D+wn2cyuxbyWVQ
++3r9LiL9qNwD/QAjyrhSN8L3Mfq+wdTHo5i0yB9ZCCpHLXSbhCqfWZwQ=
++=dwx2
++-----END PGP PUBLIC KEY BLOCK-----
+diff --git a/tests/openpgp/import-incomplete/primary+subkey+sub-sig.asc b/tests/openpgp/import-incomplete/primary+subkey+sub-sig.asc
+new file mode 100644
+index 0000000..dc47a02
+--- /dev/null
++++ b/tests/openpgp/import-incomplete/primary+subkey+sub-sig.asc
+@@ -0,0 +1,10 @@
++-----BEGIN PGP PUBLIC KEY BLOCK-----
++Comment: [B] primary key, subkey, subkey binding sig (no user ID)
++
++mDMEXNmUGRYJKwYBBAHaRw8BAQdA75R8VlchvmEd2Iz/8l07RoKUaUPDB71Ao1zZ
++631VAN24OARc2ZQhEgorBgEEAZdVAQUBAQdABsd5ha0AWXdXcSmfeiWIfrNcGqQK
++j++lwwWDAOlkVicDAQgHiHgEGBYIACAWIQS0aY+VvNh/4EjMyikIQ9qWmqja+wUC
++XNmUIQIbDAAKCRAIQ9qWmqja++vFAP98G1L+1/rWTGbsnxOAV2RocBYIroAvsbkR
++Ly6FdP8YNwEA7jOgT05CoKIe37MstpOz23mM80AK369Ca3JMmKKCQgg=
++=xuDu
++-----END PGP PUBLIC KEY BLOCK-----
+diff --git a/tests/openpgp/import-incomplete/primary+uid-sig.asc b/tests/openpgp/import-incomplete/primary+uid-sig.asc
+new file mode 100644
+index 0000000..134607d
+--- /dev/null
++++ b/tests/openpgp/import-incomplete/primary+uid-sig.asc
+@@ -0,0 +1,10 @@
++-----BEGIN PGP PUBLIC KEY BLOCK-----
++Comment: [C] primary key and self-sig expiring in 2024 (no user ID)
++
++mDMEXNmUGRYJKwYBBAHaRw8BAQdA75R8VlchvmEd2Iz/8l07RoKUaUPDB71Ao1zZ
++631VAN2IlgQTFggAPgIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgBYhBLRpj5W8
++2H/gSMzKKQhD2paaqNr7BQJc2ZR1BQkJZgHcAAoJEAhD2paaqNr79soA/0lWkUsu
++3NLwgbni6EzJxnTzgeNMpljqNpipHAwfix9hAP93AVtFdC8g7hdUZxawobl9lnSN
++9ohXOEBWvdJgVv2YAg==
++=KWIK
++-----END PGP PUBLIC KEY BLOCK-----
+diff --git a/tests/openpgp/import-incomplete/primary+uid.asc b/tests/openpgp/import-incomplete/primary+uid.asc
+new file mode 100644
+index 0000000..055f300
+--- /dev/null
++++ b/tests/openpgp/import-incomplete/primary+uid.asc
+@@ -0,0 +1,10 @@
++-----BEGIN PGP PUBLIC KEY BLOCK-----
++Comment: [A] primary key, user ID, and self-sig expiring in 2021
++
++mDMEXNmUGRYJKwYBBAHaRw8BAQdA75R8VlchvmEd2Iz/8l07RoKUaUPDB71Ao1zZ
++631VAN20CHRlc3Qga2V5iJYEExYIAD4WIQS0aY+VvNh/4EjMyikIQ9qWmqja+wUC
++XNmUGQIbAwUJA8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRAIQ9qWmqja
+++0G1AQDdQiwhXxjXLMqoth+D4SigVHTJK8ORwifzsy3UE7mPGwD/aZ67XbAF/lgI
++kv2O1Jo0u9BL9RNNF+L0DM7rAFbfMAs=
++=1eII
++-----END PGP PUBLIC KEY BLOCK-----
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..3d8fed9
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,24 @@
+debian-packaging/avoid-beta-warning.patch
+debian-packaging/avoid-regenerating-defsincdate-use-shipped-file.patch
+block-ptrace-on-secret-daemons/Avoid-simple-memory-dumps-via-ptrace.patch
+dirmngr-idling/dirmngr-hkp-Avoid-potential-race-condition-when-some.patch
+dirmngr-idling/dirmngr-Avoid-need-for-hkp-housekeeping.patch
+dirmngr-idling/dirmngr-Avoid-automatically-checking-upstream-swdb.patch
+gpg-agent-idling/agent-Create-framework-of-scheduled-timers.patch
+gpg-agent-idling/agent-Allow-threads-to-interrupt-main-select-loop-wi.patch
+gpg-agent-idling/agent-Avoid-tight-timer-tick-when-possible.patch
+gpg-agent-idling/agent-Avoid-scheduled-checks-on-socket-when-inotify-.patch
+from-master/gpg-default-to-3072-bit-keys.patch
+from-master/gpg-default-to-AES-256.patch
+update-defaults/gpg-Default-to-SHA-512-for-all-signature-types-on-RS.patch
+update-defaults/gpg-Prefer-SHA-512-and-SHA-384-in-personal-digest.patch
+import-merge-without-userid/tests-add-test-cases-for-import-without-uid.patch
+import-merge-without-userid/gpg-allow-import-of-previously-known-keys-even-without-UI.patch
+import-merge-without-userid/gpg-accept-subkeys-with-a-good-revocation-but-no-self-sig.patch
+dirmngr-Only-use-SKS-pool-CA-for-SKS-pool.patch
+Use-hkps-keys.openpgp.org-as-the-default-keyserver.patch
+Make-gpg-zip-use-tar-from-PATH.patch
+gpg-drop-import-clean-from-default-keyserver-import-optio.patch
+from-master/gpg-change-agent-spawn-2019-07-24-v2.patch
+cherry-picked/1617856888.gnupg-2.3.0-4-gab66c4357.scd-fix-ccid-driver-for-scm-spr332-spr532.patch
+cherry-picked/g10-Fix-garbled-status-messages-in-NOTATION_DATA.patch
diff --git a/debian/patches/update-defaults/gpg-Default-to-SHA-512-for-all-signature-types-on-RS.patch b/debian/patches/update-defaults/gpg-Default-to-SHA-512-for-all-signature-types-on-RS.patch
new file mode 100644
index 0000000..2cc3eaa
--- /dev/null
+++ b/debian/patches/update-defaults/gpg-Default-to-SHA-512-for-all-signature-types-on-RS.patch
@@ -0,0 +1,64 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Thu, 7 Sep 2017 18:49:35 -0400
+Subject: gpg: Default to SHA-512 for all signature types on RSA keys.
+
+* g10/main.h (DEFAULT_DIGEST_ALGO): Use SHA512 instead of SHA256 in
+--gnupg mode (leave strict RFC and PGP modes alone).
+* configure.ac: Do not allow disabling sha512.
+* g10/misc.c (map_md_openpgp_to_gcry): Always support SHA512.
+
+--
+
+SHA512 is more performant on most 64-bit platforms than SHA256, and
+offers a better security margin. It is also widely implemented.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ configure.ac | 2 +-
+ g10/main.h | 2 +-
+ g10/misc.c | 5 +----
+ 3 files changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 2d8b050..4b9d908 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -317,7 +317,7 @@ GNUPG_GPG_DISABLE_ALGO([rmd160],[RIPE-MD160 hash])
+ GNUPG_GPG_DISABLE_ALGO([sha224],[SHA-224 hash])
+ # SHA256 is a MUST algorithm for GnuPG.
+ GNUPG_GPG_DISABLE_ALGO([sha384],[SHA-384 hash])
+-GNUPG_GPG_DISABLE_ALGO([sha512],[SHA-512 hash])
++# SHA512 is a MUST algorithm for GnuPG.
+
+
+ # Allow disabling of zip support.
+diff --git a/g10/main.h b/g10/main.h
+index 1983e42..388eae3 100644
+--- a/g10/main.h
++++ b/g10/main.h
+@@ -41,7 +41,7 @@
+ # define DEFAULT_CIPHER_ALGO CIPHER_ALGO_3DES
+ #endif
+
+-#define DEFAULT_DIGEST_ALGO ((GNUPG)? DIGEST_ALGO_SHA256:DIGEST_ALGO_SHA1)
++#define DEFAULT_DIGEST_ALGO ((GNUPG)? DIGEST_ALGO_SHA512:DIGEST_ALGO_SHA1)
+ #define DEFAULT_S2K_DIGEST_ALGO DIGEST_ALGO_SHA1
+ #ifdef HAVE_ZIP
+ # define DEFAULT_COMPRESS_ALGO COMPRESS_ALGO_ZIP
+diff --git a/g10/misc.c b/g10/misc.c
+index 634d303..6fc2d58 100644
+--- a/g10/misc.c
++++ b/g10/misc.c
+@@ -849,11 +849,8 @@ map_md_openpgp_to_gcry (digest_algo_t algo)
+ case DIGEST_ALGO_SHA384: return 0;
+ #endif
+
+-#ifdef GPG_USE_SHA512
+ case DIGEST_ALGO_SHA512: return GCRY_MD_SHA512;
+-#else
+- case DIGEST_ALGO_SHA512: return 0;
+-#endif
++
+ default: return 0;
+ }
+ }
diff --git a/debian/patches/update-defaults/gpg-Prefer-SHA-512-and-SHA-384-in-personal-digest.patch b/debian/patches/update-defaults/gpg-Prefer-SHA-512-and-SHA-384-in-personal-digest.patch
new file mode 100644
index 0000000..c55502a
--- /dev/null
+++ b/debian/patches/update-defaults/gpg-Prefer-SHA-512-and-SHA-384-in-personal-digest.patch
@@ -0,0 +1,46 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Wed, 3 Jan 2018 12:34:26 -0500
+Subject: gpg: Prefer SHA-512 and SHA-384 in personal-digest-preferences.
+
+* g10/keygen.c (keygen_set_std_prefs): prefer SHA-512
+and SHA-384 by default.
+
+--
+
+In 8ede3ae29a39641a2f98ad9a4cf61ea99085a892, upstream changed the
+defaults for --default-preference-list to advertise a preference for
+SHA-512, without touching --personal-digest-preferences. This makes
+the same change for --personal-digest-preferences, since every modern
+OpenPGP library supports them all.
+
+Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+---
+ g10/keygen.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/g10/keygen.c b/g10/keygen.c
+index 79d4579..cb92468 100644
+--- a/g10/keygen.c
++++ b/g10/keygen.c
+@@ -391,16 +391,16 @@ keygen_set_std_prefs (const char *string,int personal)
+ if (personal)
+ {
+ /* The default internal hash algo order is:
+- * SHA-256, SHA-384, SHA-512, SHA-224, SHA-1.
++ * SHA-512, SHA-384, SHA-256, SHA-224, SHA-1.
+ */
+- if (!openpgp_md_test_algo (DIGEST_ALGO_SHA256))
+- strcat (dummy_string, "H8 ");
++ if (!openpgp_md_test_algo (DIGEST_ALGO_SHA512))
++ strcat (dummy_string, "H10 ");
+
+ if (!openpgp_md_test_algo (DIGEST_ALGO_SHA384))
+ strcat (dummy_string, "H9 ");
+
+- if (!openpgp_md_test_algo (DIGEST_ALGO_SHA512))
+- strcat (dummy_string, "H10 ");
++ if (!openpgp_md_test_algo (DIGEST_ALGO_SHA256))
++ strcat (dummy_string, "H8 ");
+ }
+ else
+ {