diff -Nru python-gnupg-0.4.3/debian/changelog python-gnupg-0.4.3/debian/changelog --- python-gnupg-0.4.3/debian/changelog 2018-09-25 15:35:29.000000000 +0000 +++ python-gnupg-0.4.3/debian/changelog 2019-04-30 18:47:20.000000000 +0000 @@ -1,3 +1,14 @@ +python-gnupg (0.4.3-1ubuntu1.19.04.1) disco-security; urgency=medium + + * SECURITY UPDATE: Improper input validation + - debian/patches/CVE-2019-6690-1.patch: Added checks to disallow + newline-type characters in passphrases. + - debian/patches/CVE-2019-6690-2.patch: Expand passphrase check to include + NUL bytes. + - CVE-2019-6690 + + -- Mike Salvatore Tue, 30 Apr 2019 14:47:20 -0400 + python-gnupg (0.4.3-1ubuntu1) cosmic; urgency=medium * Increase the verbosity of the test run. diff -Nru python-gnupg-0.4.3/debian/control python-gnupg-0.4.3/debian/control --- python-gnupg-0.4.3/debian/control 2018-06-16 08:06:36.000000000 +0000 +++ python-gnupg-0.4.3/debian/control 2019-04-30 18:47:20.000000000 +0000 @@ -1,5 +1,6 @@ Source: python-gnupg -Maintainer: Elena Grandi +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Elena Grandi Uploaders: Debian Python Modules Team Section: python Priority: optional diff -Nru python-gnupg-0.4.3/debian/patches/CVE-2019-6690-1.patch python-gnupg-0.4.3/debian/patches/CVE-2019-6690-1.patch --- python-gnupg-0.4.3/debian/patches/CVE-2019-6690-1.patch 1970-01-01 00:00:00.000000000 +0000 +++ python-gnupg-0.4.3/debian/patches/CVE-2019-6690-1.patch 2019-04-30 18:46:44.000000000 +0000 @@ -0,0 +1,108 @@ +Backport of: + +From 39eca266dd837e2ad89c94eb17b7a6f50b25e7cf Mon Sep 17 00:00:00 2001 +From: Vinay Sajip +Date: Wed, 23 Jan 2019 14:16:48 +0000 +Subject: [PATCH] Added checks to disallow newline-type characters in + passphrases. + +--- + gnupg.py | 21 +++++++++++++++++++-- + test_gnupg.py | 4 ++++ + 3 files changed, 26 insertions(+), 3 deletions(-) + +--- a/gnupg.py ++++ b/gnupg.py +@@ -27,7 +27,7 @@ Vinay Sajip to make use of the subproces + and so does not work on Windows). Renamed to gnupg.py to avoid confusion with + the previous versions. + +-Modifications Copyright (C) 2008-2018 Vinay Sajip. All rights reserved. ++Modifications Copyright (C) 2008-2019 Vinay Sajip. All rights reserved. + + A unittest harness (test_gnupg.py) has also been added. + """ +@@ -996,9 +996,19 @@ class GPG(object): + args.extend(['--yes']) + args.extend(['--output', no_quote(output)]) + ++ def is_valid_passphrase(self, passphrase): ++ """ ++ Confirm that the passphrase doesn't contain newline-type characters - ++ it is passed in a pipe to gpg, and so not checking could lead to ++ spoofing attacks by passing arbitrary text after passphrase and newline. ++ """ ++ return ('\n' not in passphrase and '\r' not in passphrase) ++ + def sign_file(self, file, keyid=None, passphrase=None, clearsign=True, + detach=False, binary=False, output=None, extra_args=None): + """sign file""" ++ if passphrase and not self.is_valid_passphrase(passphrase): ++ raise ValueError('Invalid passphrase') + logger.debug("sign_file: %s", file) + if binary: # pragma: no cover + args = ['-s'] +@@ -1159,6 +1169,8 @@ class GPG(object): + via pinentry, you should specify expect_passphrase=False. (It's only + checked for GnuPG >= 2.1). + """ ++ if passphrase and not self.is_valid_passphrase(passphrase): ++ raise ValueError('Invalid passphrase') + which='key' + if secret: # pragma: no cover + if (self.version >= (2, 1) and passphrase is None and +@@ -1196,7 +1208,8 @@ class GPG(object): + via pinentry, you should specify expect_passphrase=False. (It's only + checked for GnuPG >= 2.1). + """ +- ++ if passphrase and not self.is_valid_passphrase(passphrase): ++ raise ValueError('Invalid passphrase') + which='' + if secret: + which='-secret-key' +@@ -1427,6 +1440,8 @@ class GPG(object): + always_trust=False, passphrase=None, + armor=True, output=None, symmetric=False, extra_args=None): + "Encrypt the message read from the file-like object 'file'" ++ if passphrase and not self.is_valid_passphrase(passphrase): ++ raise ValueError('Invalid passphrase') + args = ['--encrypt'] + if symmetric: + # can't be False or None - could be True or a cipher algo value +@@ -1515,6 +1530,8 @@ class GPG(object): + + def decrypt_file(self, file, always_trust=False, passphrase=None, + output=None, extra_args=None): ++ if passphrase and not self.is_valid_passphrase(passphrase): ++ raise ValueError('Invalid passphrase') + args = ["--decrypt"] + if output: # write the output to a file with the specified name + self.set_output_without_confirmation(args, output) +--- a/test_gnupg.py ++++ b/test_gnupg.py +@@ -489,6 +489,7 @@ class GPGTestCase(unittest.TestCase): + data = data.encode(gpg.encoding) + edata = str(gpg.encrypt(data, barbara)) + self.assertNotEqual(data, edata, "Data must have changed") ++ self.assertRaises(ValueError, gpg.decrypt, edata, passphrase="bbr\nown") + ddata = gpg.decrypt(edata, passphrase="bbrown") + if data != ddata.data: # pragma: no cover + logger.debug("was: %r", data) +@@ -503,6 +504,8 @@ class GPGTestCase(unittest.TestCase): + logger.debug("test_encryption_and_decryption ends") + # Test symmetric encryption + data = "chippy was here" ++ self.assertRaises(ValueError, gpg.encrypt, data, None, ++ passphrase='bbr\nown', symmetric=True) + edata = str(gpg.encrypt(data, None, passphrase='bbrown', symmetric=True)) + ddata = gpg.decrypt(edata, passphrase='bbrown') + self.assertEqual(data, str(ddata)) +@@ -603,6 +606,7 @@ class GPGTestCase(unittest.TestCase): + else: + data = unicode('Hello, André', self.gpg.encoding) + data = data.encode(self.gpg.encoding) ++ self.assertRaises(ValueError, self.gpg.sign, data, keyid=key.fingerprint, passphrase="bbr\nown") + sig = self.gpg.sign(data, keyid=key.fingerprint, passphrase='bbrown') + self.assertFalse(sig, "Bad passphrase should fail") + sig = self.gpg.sign(data, keyid=key.fingerprint, passphrase='aable') diff -Nru python-gnupg-0.4.3/debian/patches/CVE-2019-6690-2.patch python-gnupg-0.4.3/debian/patches/CVE-2019-6690-2.patch --- python-gnupg-0.4.3/debian/patches/CVE-2019-6690-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ python-gnupg-0.4.3/debian/patches/CVE-2019-6690-2.patch 2019-04-30 18:46:43.000000000 +0000 @@ -0,0 +1,55 @@ +Backport of: + +From 3003b654ca1c29b0510a54b9848571b3ad57df19 Mon Sep 17 00:00:00 2001 +From: Vinay Sajip +Date: Wed, 23 Jan 2019 19:35:49 +0000 +Subject: [PATCH] Expand passphrase check to include NUL bytes. + +--- + gnupg.py | 3 ++- + test_gnupg.py | 8 ++++++++ + 3 files changed, 12 insertions(+), 2 deletions(-) + +--- a/gnupg.py ++++ b/gnupg.py +@@ -1002,7 +1002,8 @@ class GPG(object): + it is passed in a pipe to gpg, and so not checking could lead to + spoofing attacks by passing arbitrary text after passphrase and newline. + """ +- return ('\n' not in passphrase and '\r' not in passphrase) ++ return ('\n' not in passphrase and '\r' not in passphrase and ++ '\x00' not in passphrase) + + def sign_file(self, file, keyid=None, passphrase=None, clearsign=True, + detach=False, binary=False, output=None, extra_args=None): +--- a/test_gnupg.py ++++ b/test_gnupg.py +@@ -489,6 +489,8 @@ class GPGTestCase(unittest.TestCase): + data = data.encode(gpg.encoding) + edata = str(gpg.encrypt(data, barbara)) + self.assertNotEqual(data, edata, "Data must have changed") ++ self.assertRaises(ValueError, gpg.decrypt, edata, passphrase="bbr\x00own") ++ self.assertRaises(ValueError, gpg.decrypt, edata, passphrase="bbr\rown") + self.assertRaises(ValueError, gpg.decrypt, edata, passphrase="bbr\nown") + ddata = gpg.decrypt(edata, passphrase="bbrown") + if data != ddata.data: # pragma: no cover +@@ -505,6 +507,10 @@ class GPGTestCase(unittest.TestCase): + # Test symmetric encryption + data = "chippy was here" + self.assertRaises(ValueError, gpg.encrypt, data, None, ++ passphrase='bbr\x00own', symmetric=True) ++ self.assertRaises(ValueError, gpg.encrypt, data, None, ++ passphrase='bbr\rown', symmetric=True) ++ self.assertRaises(ValueError, gpg.encrypt, data, None, + passphrase='bbr\nown', symmetric=True) + edata = str(gpg.encrypt(data, None, passphrase='bbrown', symmetric=True)) + ddata = gpg.decrypt(edata, passphrase='bbrown') +@@ -606,6 +612,8 @@ class GPGTestCase(unittest.TestCase): + else: + data = unicode('Hello, André', self.gpg.encoding) + data = data.encode(self.gpg.encoding) ++ self.assertRaises(ValueError, self.gpg.sign, data, keyid=key.fingerprint, passphrase="bbr\x00own") ++ self.assertRaises(ValueError, self.gpg.sign, data, keyid=key.fingerprint, passphrase="bbr\rown") + self.assertRaises(ValueError, self.gpg.sign, data, keyid=key.fingerprint, passphrase="bbr\nown") + sig = self.gpg.sign(data, keyid=key.fingerprint, passphrase='bbrown') + self.assertFalse(sig, "Bad passphrase should fail") diff -Nru python-gnupg-0.4.3/debian/patches/series python-gnupg-0.4.3/debian/patches/series --- python-gnupg-0.4.3/debian/patches/series 2018-09-25 15:35:29.000000000 +0000 +++ python-gnupg-0.4.3/debian/patches/series 2019-04-30 18:46:14.000000000 +0000 @@ -1,2 +1,4 @@ skip_network_needing_test.patch log-on-stderr.diff +CVE-2019-6690-1.patch +CVE-2019-6690-2.patch