[Python-modules-commits] [python-gnupg] 06/08: merge patched into master

Elena Grandi valhalla-guest at moszumanska.debian.org
Sat Apr 8 06:44:44 UTC 2017


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

valhalla-guest pushed a commit to branch gpg2
in repository python-gnupg.

commit baa7448e13c6498610d618cc4a62702bb46a8fc4
Merge: 1ec436f 9bb7af6
Author: Elena Grandi <valhalla-d at trueelena.org>
Date:   Tue Feb 28 15:36:01 2017 +0100

    merge patched into master

 debian/.git-dpm                                    |   4 +-
 .../0002-Default-on-using-gpg1-as-gpgbinary.patch  |  36 ------
 ...inentry-mode-loopback-for-2.1.x-and-later.patch |  26 ++++
 ...oid-exceptions-on-unknown-status-keywords.patch | 141 +++++++++++++++++++++
 ...fixed-list-mode-and-batch-and-with-colons.patch |  87 +++++++++++++
 ...risky-scan_keys-operation-on-modern-GnuPG.patch |  38 ++++++
 ...ous-test-suite-failures-due-to-socket-rem.patch | 110 ++++++++++++++++
 debian/patches/series                              |   6 +-
 gnupg.py                                           |  88 +++++--------
 test_gnupg.py                                      |   8 +-
 10 files changed, 443 insertions(+), 101 deletions(-)

diff --cc debian/.git-dpm
index b12a216,0000000..3edc140
mode 100644,000000..100644
--- a/debian/.git-dpm
+++ b/debian/.git-dpm
@@@ -1,11 -1,0 +1,11 @@@
 +# see git-dpm(1) from git-dpm package
- 09a1f18cf9864dba35db34744200f7e40b401d6f
- 09a1f18cf9864dba35db34744200f7e40b401d6f
++9bb7af658e91c2228183d8d1fbc759299116e629
++9bb7af658e91c2228183d8d1fbc759299116e629
 +53585fde665095b170b0706129af9238b168becf
 +53585fde665095b170b0706129af9238b168becf
 +python-gnupg_0.3.9.orig.tar.gz
 +75fd5ed615edfaf5b3e5ef0af0d14f0e3c6cd0b1
 +42260
 +debianTag="debian/%e%v"
 +patchedTag="patched/%e%v"
 +upstreamTag="upstream/%e%u"
diff --cc debian/patches/0002-use-pinentry-mode-loopback-for-2.1.x-and-later.patch
index 0000000,0000000..0f82430
new file mode 100644
--- /dev/null
+++ b/debian/patches/0002-use-pinentry-mode-loopback-for-2.1.x-and-later.patch
@@@ -1,0 -1,0 +1,26 @@@
++From 9f3c15b8990970e91aa33779ba03a26fdd94b115 Mon Sep 17 00:00:00 2001
++From: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
++Date: Fri, 17 Feb 2017 17:23:04 -0500
++Subject: use --pinentry-mode loopback for 2.1.x and later
++
++If the user specifies an explicit passphrase rather than relying on
++the gpg-agent for granting access, then we should try to pass the
++passphrase to the agent.  In 2.1.x, passing a passphrase to the agent
++is done with "--pinentry-mode loopback", so we add that here.
++---
++ gnupg.py | 2 ++
++ 1 file changed, 2 insertions(+)
++
++diff --git a/gnupg.py b/gnupg.py
++index 2a08d96..0412531 100644
++--- a/gnupg.py
+++++ b/gnupg.py
++@@ -783,6 +783,8 @@ class GPG(object):
++                 cmd.extend(['--secret-keyring', no_quote(fn)])
++         if passphrase:
++             cmd.extend(['--batch', '--passphrase-fd', '0'])
+++            if self.version >= (2,1):
+++                cmd.extend(['--pinentry-mode', 'loopback'])
++         if self.use_agent:  # pragma: no cover
++             cmd.append('--use-agent')
++         if self.options:
diff --cc debian/patches/0003-Avoid-exceptions-on-unknown-status-keywords.patch
index 0000000,0000000..eb9737d
new file mode 100644
--- /dev/null
+++ b/debian/patches/0003-Avoid-exceptions-on-unknown-status-keywords.patch
@@@ -1,0 -1,0 +1,141 @@@
++From 6787db516ce3896d8e566ecc8343bc5d98d74795 Mon Sep 17 00:00:00 2001
++From: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
++Date: Fri, 17 Feb 2017 17:23:05 -0500
++Subject: Avoid exceptions on unknown status keywords
++
++in upstream GnuPG, doc/DETAILS says:
++
++---------
++* Format of the --status-fd output
++
++  Every line is prefixed with "[GNUPG:] ", followed by a keyword with
++  the type of the status line and some arguments depending on the type
++  (maybe none); an application should always be willing to ignore
++  unknown keywords that may be emitted by future versions of GnuPG.
++  Also, new versions of GnuPG may add arguments to existing keywords.
++  Any additional arguments should be ignored for forward-compatibility.
++---------
++
++This set of changes ensures that any time we're looking for status
++messages it is only to look for them positively -- if we encounter an
++unknown or other status message, we'll just let it slide by without an
++error.
++---
++ gnupg.py | 47 ++++-------------------------------------------
++ 1 file changed, 4 insertions(+), 43 deletions(-)
++
++diff --git a/gnupg.py b/gnupg.py
++index 0412531..7ff9f11 100644
++--- a/gnupg.py
+++++ b/gnupg.py
++@@ -240,14 +240,6 @@ class Verify(object):
++         if key in self.TRUST_LEVELS:
++             self.trust_text = key
++             self.trust_level = self.TRUST_LEVELS[key]
++-        elif key in ("RSA_OR_IDEA", "NODATA", "IMPORT_RES", "PLAINTEXT",
++-                     "PLAINTEXT_LENGTH", "POLICY_URL", "DECRYPTION_INFO",
++-                     "DECRYPTION_OKAY", "INV_SGNR", "FILE_START", "FILE_ERROR",
++-                     "FILE_DONE", "PKA_TRUST_GOOD", "PKA_TRUST_BAD", "BADMDC",
++-                     "GOODMDC", "NO_SGNR", "NOTATION_NAME", "NOTATION_DATA",
++-                     "PROGRESS", "PINENTRY_LAUNCHED", "NEWSIG",
++-                     "KEY_CONSIDERED"):
++-            pass
++         elif key == "BADSIG":  # pragma: no cover
++             self.valid = False
++             self.status = 'signature bad'
++@@ -286,12 +278,6 @@ class Verify(object):
++             self.valid = False
++             self.key_id = value
++             self.status = 'no public key'
++-        elif key in ("KEYEXPIRED", "SIGEXPIRED", "KEYREVOKED"):  # pragma: no cover
++-            # these are useless in verify, since they are spit out for any
++-            # pub/subkeys on the key, not just the one doing the signing.
++-            # if we want to check for signatures with expired key,
++-            # the relevant flag is EXPKEYSIG or REVKEYSIG.
++-            pass
++         elif key in ("EXPKEYSIG", "REVKEYSIG"):  # pragma: no cover
++             # signed with expired or revoked key
++             self.valid = False
++@@ -309,8 +295,6 @@ class Verify(object):
++             else:
++                 # N.B. there might be other reasons
++                 self.status = 'incorrect passphrase'
++-        else:
++-            raise ValueError("Unknown status message: %r" % key)
++ 
++ class ImportResult(object):
++     "Handle status messages for --import"
++@@ -385,8 +369,6 @@ class ImportResult(object):
++         elif key == "SIGEXPIRED":  # pragma: no cover
++             self.results.append({'fingerprint': None,
++                 'problem': '0', 'text': 'Signature expired'})
++-        else:  # pragma: no cover
++-            raise ValueError("Unknown status message: %r" % key)
++ 
++     def summary(self):
++         l = []
++@@ -552,14 +534,8 @@ class Crypt(Verify, TextHandler):
++     __bool__ = __nonzero__
++ 
++     def handle_status(self, key, value):
++-        if key in ("ENC_TO", "USERID_HINT", "GOODMDC", "END_DECRYPTION",
++-                   "BEGIN_SIGNING", "NO_SECKEY", "ERROR", "NODATA", "PROGRESS",
++-                   "CARDCTRL", "BADMDC", "SC_OP_FAILURE", "SC_OP_SUCCESS",
++-                   "PINENTRY_LAUNCHED"):
++-            # in the case of ERROR, this is because a more specific error
++-            # message will have come first
++-            if key == "NODATA":
++-                self.status = "no data was provided"
+++        if key == "NODATA":
+++            self.status = "no data was provided"
++         elif key in ("NEED_PASSPHRASE", "BAD_PASSPHRASE", "GOOD_PASSPHRASE",
++                      "MISSING_PASSPHRASE", "DECRYPTION_FAILED",
++                      "KEY_NOT_CREATED", "NEED_PASSPHRASE_PIN"):
++@@ -604,13 +580,8 @@ class GenKey(object):
++         return self.fingerprint or ''
++ 
++     def handle_status(self, key, value):
++-        if key in ("PROGRESS", "GOOD_PASSPHRASE", "NODATA", "KEY_NOT_CREATED",
++-                   "PINENTRY_LAUNCHED"):
++-            pass
++-        elif key == "KEY_CREATED":
+++        if key == "KEY_CREATED":
++             (self.type,self.fingerprint) = value.split()
++-        else:
++-            raise ValueError("Unknown status message: %r" % key)
++ 
++ class ExportResult(GenKey):
++     """Handle status messages for --export[-secret-key].
++@@ -643,8 +614,6 @@ class DeleteResult(object):
++         if key == "DELETE_PROBLEM":  # pragma: no cover
++             self.status = self.problem_reason.get(value,
++                                                   "Unknown error: %r" % value)
++-        else:  # pragma: no cover
++-            raise ValueError("Unknown status message: %r" % key)
++ 
++     def __nonzero__(self):
++         return self.status == 'ok'
++@@ -666,13 +635,7 @@ class Sign(TextHandler):
++     __bool__ = __nonzero__
++ 
++     def handle_status(self, key, value):
++-        if key in ("USERID_HINT", "NEED_PASSPHRASE", "BAD_PASSPHRASE",
++-                   "GOOD_PASSPHRASE", "BEGIN_SIGNING", "CARDCTRL", "INV_SGNR",
++-                   "NO_SGNR", "MISSING_PASSPHRASE", "NEED_PASSPHRASE_PIN",
++-                   "SC_OP_FAILURE", "SC_OP_SUCCESS", "PROGRESS",
++-                   "PINENTRY_LAUNCHED"):
++-            pass
++-        elif key in ("KEYEXPIRED", "SIGEXPIRED"):  # pragma: no cover
+++        if key in ("KEYEXPIRED", "SIGEXPIRED"):  # pragma: no cover
++             self.status = 'key expired'
++         elif key == "KEYREVOKED":  # pragma: no cover
++             self.status = 'key revoked'
++@@ -681,8 +644,6 @@ class Sign(TextHandler):
++              algo, self.hash_algo, cls,
++              self.timestamp, self.fingerprint
++              ) = value.split()
++-        else:  # pragma: no cover
++-            raise ValueError("Unknown status message: %r" % key)
++ 
++ VERSION_RE = re.compile(r'gpg \(GnuPG\) (\d+(\.\d+)*)'.encode('ascii'), re.I)
++ HEX_DIGITS_RE = re.compile(r'[0-9a-f]+$', re.I)
diff --cc debian/patches/0004-always-use-fixed-list-mode-and-batch-and-with-colons.patch
index 0000000,0000000..97757ee
new file mode 100644
--- /dev/null
+++ b/debian/patches/0004-always-use-fixed-list-mode-and-batch-and-with-colons.patch
@@@ -1,0 -1,0 +1,87 @@@
++From e9c796033ca3489f24468475694f6fad008c9c0b Mon Sep 17 00:00:00 2001
++From: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
++Date: Fri, 17 Feb 2017 17:23:06 -0500
++Subject: always use --fixed-list-mode and --batch and --with-colons
++
++gpg is being invoked programmatically, so it should always use
++--batch.
++
++--fixed-list-mode is also the standard, since we have no intention of
++ever using the non-fixed mode and modern versions of GnuPG don't even
++have the option of doing so.
++
++we also want --with-colons: for any output, are going to be parsing it
++directly, so we don't want the human-readable form.
++---
++ gnupg.py | 16 ++++++++--------
++ 1 file changed, 8 insertions(+), 8 deletions(-)
++
++diff --git a/gnupg.py b/gnupg.py
++index 7ff9f11..9090599 100644
++--- a/gnupg.py
+++++ b/gnupg.py
++@@ -733,6 +733,7 @@ class GPG(object):
++         a passphrase will be sent to GPG, else False.
++         """
++         cmd = [self.gpgbinary, '--status-fd', '2', '--no-tty']
+++        cmd.extend(['--fixed-list-mode', '--batch', '--with-colons'])
++         if self.gnupghome:
++             cmd.extend(['--homedir',  no_quote(self.gnupghome)])
++         if self.keyring:
++@@ -743,7 +744,7 @@ class GPG(object):
++             for fn in self.secret_keyring:
++                 cmd.extend(['--secret-keyring', no_quote(fn)])
++         if passphrase:
++-            cmd.extend(['--batch', '--passphrase-fd', '0'])
+++            cmd.extend(['--passphrase-fd', '0'])
++             if self.version >= (2,1):
++                 cmd.extend(['--pinentry-mode', 'loopback'])
++         if self.use_agent:  # pragma: no cover
++@@ -874,7 +875,7 @@ class GPG(object):
++         "If writing to a file which exists, avoid a confirmation message."
++         if os.path.exists(output):
++             # We need to avoid an overwrite confirmation message
++-            args.extend(['--batch', '--yes'])
+++            args.extend(['--yes'])
++         args.extend(['--output', no_quote(output)])
++ 
++     def sign_file(self, file, keyid=None, passphrase=None, clearsign=True,
++@@ -1069,7 +1070,7 @@ class GPG(object):
++             fingerprints = [no_quote(s) for s in fingerprints]
++         else:
++             fingerprints = [no_quote(fingerprints)]
++-        args = ['--batch', '--delete-%s' % which]
+++        args = ['--delete-%s' % which]
++         args.extend(fingerprints)
++         result = self.result_map['delete'](self)
++         p = self._open_subprocess(args)
++@@ -1148,9 +1149,8 @@ class GPG(object):
++             which='keys'
++         if secret:
++             which='secret-keys'
++-        args = ['--list-%s' % which, '--fixed-list-mode',
++-                '--fingerprint', '--fingerprint',   # get subkey FPs, too
++-                '--with-colons']
+++        args = ['--list-%s' % which,
+++                '--fingerprint', '--fingerprint'] # get subkey FPs, too
++         if keys:
++             if isinstance(keys, string_types):
++                 keys = [keys]
++@@ -1188,7 +1188,7 @@ class GPG(object):
++         query = query.strip()
++         if HEX_DIGITS_RE.match(query):
++             query = '0x' + query
++-        args = ['--fixed-list-mode', '--fingerprint', '--with-colons',
+++        args = ['--fingerprint',
++                 '--keyserver', no_quote(keyserver), '--search-keys',
++                 no_quote(query)]
++         p = self._open_subprocess(args)
++@@ -1225,7 +1225,7 @@ class GPG(object):
++         >>> assert not result
++ 
++         """
++-        args = ["--gen-key", "--batch"]
+++        args = ["--gen-key"]
++         result = self.result_map['generate'](self)
++         f = _make_binary_stream(input, self.encoding)
++         self._handle_io(args, f, result, binary=True)
diff --cc debian/patches/0005-Avoid-risky-scan_keys-operation-on-modern-GnuPG.patch
index 0000000,0000000..6c43d98
new file mode 100644
--- /dev/null
+++ b/debian/patches/0005-Avoid-risky-scan_keys-operation-on-modern-GnuPG.patch
@@@ -1,0 -1,0 +1,38 @@@
++From 7963728cccb72bbac3f9afdd5f9bc64f37549f19 Mon Sep 17 00:00:00 2001
++From: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
++Date: Fri, 17 Feb 2017 17:23:07 -0500
++Subject: Avoid risky scan_keys() operation on modern GnuPG.
++
++Please see comments from Werner Koch at:
++
++https://bugs.gnupg.org/gnupg/issue2942
++---
++ gnupg.py | 13 +++++++++++--
++ 1 file changed, 11 insertions(+), 2 deletions(-)
++
++diff --git a/gnupg.py b/gnupg.py
++index 9090599..137a6b0 100644
++--- a/gnupg.py
+++++ b/gnupg.py
++@@ -1163,10 +1163,19 @@ class GPG(object):
++         List details of an ascii armored or binary key file
++         without first importing it to the local keyring.
++ 
++-        The function achieves this by running:
+++        The function achieves this on modern GnuPG by running:
+++
+++        $ gpg --dry-run --import-options import-show --import
+++
+++        On older versions, it does the *much* riskier:
+++
++         $ gpg --with-fingerprint --with-colons filename
++         """
++-        args = ['--with-fingerprint', '--with-colons']
+++        if self.version >= (2, 1, 14):
+++            args = ['--dry-run', '--import-options', 'import-show', '--import']
+++        else:
+++            logger.warning('Warning! trying to list packets, but if the file is not a keyring, might accidentally decrypt')
+++            args = ['--with-fingerprint']
++         args.append(no_quote(filename))
++         p = self._open_subprocess(args)
++         return self._get_list_output(p, 'scan')
diff --cc debian/patches/0006-Avoid-spurious-test-suite-failures-due-to-socket-rem.patch
index 0000000,0000000..9f57f1a
new file mode 100644
--- /dev/null
+++ b/debian/patches/0006-Avoid-spurious-test-suite-failures-due-to-socket-rem.patch
@@@ -1,0 -1,0 +1,110 @@@
++From 9bb7af658e91c2228183d8d1fbc759299116e629 Mon Sep 17 00:00:00 2001
++From: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
++Date: Fri, 17 Feb 2017 17:23:08 -0500
++Subject: Avoid spurious test suite failures due to socket removal race.
++
++When gpg-agent notices that its primary socket has been removed, it
++shuts down.  When it shuts down, it closes and unlinks its other
++sockets as well.
++
++These rmtree invocations look like they might be getting the list of
++files to delete and then unlinking them one at a time.
++
++The result is a lot of errors like:
++
++File "/home/dkg/src/python-gnupg/python-gnupg/gnupg.py", line 1157, in gnupg.GPG.list_keys
++Failed example:
++    shutil.rmtree("keys")
++Exception raised:
++    Traceback (most recent call last):
++      File "/usr/lib/python3.5/doctest.py", line 1321, in __run
++        compileflags, 1), test.globs)
++      File "<doctest gnupg.GPG.list_keys[1]>", line 1, in <module>
++        shutil.rmtree("keys")
++      File "/usr/lib/python3.5/shutil.py", line 480, in rmtree
++        _rmtree_safe_fd(fd, path, onerror)
++      File "/usr/lib/python3.5/shutil.py", line 438, in _rmtree_safe_fd
++        onerror(os.unlink, fullname, sys.exc_info())
++      File "/usr/lib/python3.5/shutil.py", line 436, in _rmtree_safe_fd
++        os.unlink(name, dir_fd=topfd)
++    FileNotFoundError: [Errno 2] No such file or directory: 'S.gpg-agent.extra'
++
++Simply making rmtree ignore errors (as this patch does) is enough to
++make the tests pass cleanly with GnuPG 2.1.18-6 and Python 3.5.3-1 on
++Debian stretch (testing).
++---
++ gnupg.py      | 8 ++++----
++ test_gnupg.py | 6 +++---
++ 2 files changed, 7 insertions(+), 7 deletions(-)
++
++diff --git a/gnupg.py b/gnupg.py
++index 137a6b0..aad114b 100644
++--- a/gnupg.py
+++++ b/gnupg.py
++@@ -1027,7 +1027,7 @@ class GPG(object):
++         """Import a key from a keyserver
++ 
++         >>> import shutil
++-        >>> shutil.rmtree("keys")
+++        >>> shutil.rmtree("keys", ignore_errors=True)
++         >>> gpg = GPG(gnupghome="keys")
++         >>> os.chmod('keys', 0x1C0)
++         >>> result = gpg.recv_keys('keyserver.ubuntu.com', '92905378')  # doctest: +SKIP
++@@ -1130,7 +1130,7 @@ class GPG(object):
++         """ list the keys currently in the keyring
++ 
++         >>> import shutil
++-        >>> shutil.rmtree("keys")
+++        >>> shutil.rmtree("keys", ignore_errors=True)
++         >>> gpg = GPG(gnupghome="keys")
++         >>> input = gpg.gen_key_input()
++         >>> result = gpg.gen_key(input)
++@@ -1184,7 +1184,7 @@ class GPG(object):
++         """ search keyserver by query (using --search-keys option)
++ 
++         >>> import shutil
++-        >>> shutil.rmtree('keys')
+++        >>> shutil.rmtree('keys', ignore_errors=True)
++         >>> gpg = GPG(gnupghome='keys')
++         >>> os.chmod('keys', 0x1C0)
++         >>> result = gpg.search_keys('<vinay_sajip at hotmail.com>')  # doctest: +SKIP
++@@ -1329,7 +1329,7 @@ class GPG(object):
++ 
++         >>> import shutil
++         >>> if os.path.exists("keys"):
++-        ...     shutil.rmtree("keys")
+++        ...     shutil.rmtree("keys", ignore_errors=True)
++         >>> gpg = GPG(gnupghome="keys")
++         >>> input = gpg.gen_key_input(passphrase='foo')
++         >>> result = gpg.gen_key(input)
++diff --git a/test_gnupg.py b/test_gnupg.py
++index 3559e62..1633b39 100644
++--- a/test_gnupg.py
+++++ b/test_gnupg.py
++@@ -153,7 +153,7 @@ class GPGTestCase(unittest.TestCase):
++         if os.path.exists(hd):
++             self.assertTrue(os.path.isdir(hd),
++                             "Not a directory: %s" % hd)
++-            shutil.rmtree(hd)
+++            shutil.rmtree(hd, ignore_errors=True)
++         self.homedir = hd
++         self.gpg = gpg = gnupg.GPG(gnupghome=hd, gpgbinary=GPGBINARY)
++         v = gpg.version
++@@ -691,7 +691,7 @@ class GPGTestCase(unittest.TestCase):
++             decfname = os.path.join(d, 'decrypted file')
++             self.do_file_encryption_and_decryption(encfname, decfname)
++         finally:
++-            shutil.rmtree(d)
+++            shutil.rmtree(d, ignore_errors=True)
++         logger.debug("test_filename_with_spaces ends")
++ 
++     @unittest.skip('requires network')
++@@ -727,7 +727,7 @@ class GPGTestCase(unittest.TestCase):
++             files = os.listdir(workdir)
++             self.assertEqual(files, ["'ab?'"])
++         finally:
++-            shutil.rmtree(workdir)
+++            shutil.rmtree(workdir, ignore_errors=True)
++ 
++     def disabled_test_signing_with_uid(self):  # pragma: no cover
++         "Test that signing with uids works. On hold for now."
diff --cc debian/patches/series
index ec45f72,0000000..465fe30
mode 100644,000000..100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@@ -1,2 -1,0 +1,6 @@@
 +skip_network_needing_test.patch
- 0002-Default-on-using-gpg1-as-gpgbinary.patch
++0002-use-pinentry-mode-loopback-for-2.1.x-and-later.patch
++0003-Avoid-exceptions-on-unknown-status-keywords.patch
++0004-always-use-fixed-list-mode-and-batch-and-with-colons.patch
++0005-Avoid-risky-scan_keys-operation-on-modern-GnuPG.patch
++0006-Avoid-spurious-test-suite-failures-due-to-socket-rem.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-gnupg.git



More information about the Python-modules-commits mailing list