diff -Nru landscape-client-18.01/debian/changelog landscape-client-18.01/debian/changelog --- landscape-client-18.01/debian/changelog 2020-02-20 17:35:22.000000000 +0000 +++ landscape-client-18.01/debian/changelog 2020-11-18 00:06:42.000000000 +0000 @@ -1,3 +1,10 @@ +landscape-client (18.01-0ubuntu3.6) bionic; urgency=medium + + * d/p/1903776-release-upgrade.patch (LP: #1903776) + - Use /etc/apt/trusted.gpg.d for validating upgrade-tool signature. + + -- Simon Poirier Tue, 17 Nov 2020 19:06:42 -0500 + landscape-client (18.01-0ubuntu3.5) bionic; urgency=medium * d/p/apt-pulse-1758529.patch: diff -Nru landscape-client-18.01/debian/patches/1903776-release-upgrade.patch landscape-client-18.01/debian/patches/1903776-release-upgrade.patch --- landscape-client-18.01/debian/patches/1903776-release-upgrade.patch 1970-01-01 00:00:00.000000000 +0000 +++ landscape-client-18.01/debian/patches/1903776-release-upgrade.patch 2020-11-18 00:06:42.000000000 +0000 @@ -0,0 +1,141 @@ +Description: Use /etc/apt/trusted.gpg.d for validating upgrade-tool signature. +Author: Simon Poirier +Origin: upstream, https://github.com/CanonicalLtd/landscape-client/commit/bcbe04db6ca45c7a0afac171e85a9c88c19253ae +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1903776 + +diff --git a/landscape/lib/gpg.py b/landscape/lib/gpg.py +index 66400d18..58218c54 100644 +--- a/landscape/lib/gpg.py ++++ b/landscape/lib/gpg.py +@@ -1,6 +1,9 @@ ++import itertools + import shutil + import tempfile + ++from glob import glob ++ + from twisted.internet.utils import getProcessOutputAndValue + + +@@ -8,14 +11,15 @@ class InvalidGPGSignature(Exception): + """Raised when the gpg signature for a given file is invalid.""" + + +-def gpg_verify(filename, signature, gpg="/usr/bin/gpg"): ++def gpg_verify(filename, signature, gpg="/usr/bin/gpg", apt_dir="/etc/apt"): + """Verify the GPG signature of a file. + + @param filename: Path to the file to verify the signature against. + @param signature: Path to signature to use. + @param gpg: Optionally, path to the GPG binary to use. ++ @param apt_dir: Optionally, path to apt trusted keyring. + @return: a C{Deferred} resulting in C{True} if the signature is +- valid, C{False} otherwise. ++ valid, C{False} otherwise. + """ + + def remove_gpg_home(ignored): +@@ -32,9 +36,17 @@ def check_gpg_exit_code(args): + "code='%d')" % (gpg, out, err, code)) + + gpg_home = tempfile.mkdtemp() +- args = ("--no-options", "--homedir", gpg_home, "--no-default-keyring", +- "--ignore-time-conflict", "--keyring", "/etc/apt/trusted.gpg", +- "--verify", signature, filename) ++ keyrings = tuple(itertools.chain(*[ ++ ("--keyring", keyring) ++ for keyring in sorted( ++ glob("{}/trusted.gpg".format(apt_dir)) + ++ glob("{}/trusted.gpg.d/*.gpg".format(apt_dir)) ++ ) ++ ])) ++ args = ( ++ "--no-options", "--homedir", gpg_home, "--no-default-keyring", ++ "--ignore-time-conflict" ++ ) + keyrings + ("--verify", signature, filename) + + result = getProcessOutputAndValue(gpg, args=args) + result.addBoth(remove_gpg_home) +diff --git a/landscape/lib/tests/test_gpg.py b/landscape/lib/tests/test_gpg.py +index e6165a26..4c84e008 100644 +--- a/landscape/lib/tests/test_gpg.py ++++ b/landscape/lib/tests/test_gpg.py +@@ -1,9 +1,10 @@ + import mock + import os ++import textwrap + import unittest + + from twisted.internet import reactor +-from twisted.internet.defer import Deferred ++from twisted.internet.defer import Deferred, inlineCallbacks + + from landscape.lib import testing + from landscape.lib.gpg import gpg_verify +@@ -16,6 +17,8 @@ def test_gpg_verify(self): + L{gpg_verify} runs the given gpg binary and returns C{True} if the + provided signature is valid. + """ ++ aptdir = self.makeDir() ++ os.mknod("{}/trusted.gpg".format(aptdir)) + gpg_options = self.makeFile() + gpg = self.makeFile("#!/bin/sh\n" + "touch $3/trustdb.gpg\n" +@@ -27,14 +30,15 @@ def test_gpg_verify(self): + @mock.patch("tempfile.mkdtemp") + def do_test(mkdtemp_mock): + mkdtemp_mock.return_value = gpg_home +- result = gpg_verify("/some/file", "/some/signature", gpg=gpg) ++ result = gpg_verify( ++ "/some/file", "/some/signature", gpg=gpg, apt_dir=aptdir) + + def check_result(ignored): + self.assertEqual( + open(gpg_options).read(), + "--no-options --homedir %s --no-default-keyring " +- "--ignore-time-conflict --keyring /etc/apt/trusted.gpg " +- "--verify /some/signature /some/file" % gpg_home) ++ "--ignore-time-conflict --keyring %s/trusted.gpg " ++ "--verify /some/signature /some/file" % (gpg_home, aptdir)) + self.assertFalse(os.path.exists(gpg_home)) + + result.addCallback(check_result) +@@ -70,3 +74,38 @@ def check_failure(failure): + + reactor.callWhenRunning(do_test) + return deferred ++ ++ @inlineCallbacks ++ def test_gpg_verify_trusted_dir(self): ++ """ ++ gpg_verify uses keys from the trusted.gpg.d if such a folder exists. ++ """ ++ apt_dir = self.makeDir() ++ os.mkdir("{}/trusted.gpg.d".format(apt_dir)) ++ os.mknod("{}/trusted.gpg.d/foo.gpg".format(apt_dir)) ++ os.mknod("{}/trusted.gpg.d/baz.gpg".format(apt_dir)) ++ os.mknod("{}/trusted.gpg.d/bad.gpg~".format(apt_dir)) ++ ++ gpg_call = self.makeFile() ++ fake_gpg = self.makeFile(textwrap.dedent("""\ ++ #!/bin/sh ++ touch $3/trustdb.gpg ++ echo -n $@ > {} ++ """).format(gpg_call)) ++ os.chmod(fake_gpg, 0o755) ++ gpg_home = self.makeDir() ++ ++ with mock.patch("tempfile.mkdtemp", return_value=gpg_home): ++ yield gpg_verify( ++ "/some/file", "/some/signature", gpg=fake_gpg, apt_dir=apt_dir) ++ ++ expected = ( ++ "--no-options --homedir {gpg_home} --no-default-keyring " ++ "--ignore-time-conflict " ++ "--keyring {apt_dir}/trusted.gpg.d/baz.gpg " ++ "--keyring {apt_dir}/trusted.gpg.d/foo.gpg " ++ "--verify /some/signature /some/file" ++ ).format(gpg_home=gpg_home, apt_dir=apt_dir) ++ with open(gpg_call) as call: ++ self.assertEqual(expected, call.read()) ++ self.assertFalse(os.path.exists(gpg_home)) diff -Nru landscape-client-18.01/debian/patches/series landscape-client-18.01/debian/patches/series --- landscape-client-18.01/debian/patches/series 2020-02-20 17:32:43.000000000 +0000 +++ landscape-client-18.01/debian/patches/series 2020-11-18 00:06:42.000000000 +0000 @@ -10,3 +10,4 @@ product-name-vminfo-1828217.patch stagger-launch-1788518.patch apt-pulse-1758529.patch +1903776-release-upgrade.patch