aboutsummaryrefslogtreecommitdiff
path: root/tests/regressions
diff options
context:
space:
mode:
Diffstat (limited to 'tests/regressions')
l---------tests/regressions/aptdaemon1
-rw-r--r--tests/regressions/test_lp722228.py152
-rw-r--r--tests/regressions/test_lp768691.py66
3 files changed, 219 insertions, 0 deletions
diff --git a/tests/regressions/aptdaemon b/tests/regressions/aptdaemon
new file mode 120000
index 0000000..9b3d444
--- /dev/null
+++ b/tests/regressions/aptdaemon
@@ -0,0 +1 @@
+../../aptdaemon \ No newline at end of file
diff --git a/tests/regressions/test_lp722228.py b/tests/regressions/test_lp722228.py
new file mode 100644
index 0000000..1f84376
--- /dev/null
+++ b/tests/regressions/test_lp722228.py
@@ -0,0 +1,152 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010 Michael Vogt <[email protected]>
+#
+# Licensed under the GNU General Public License Version 2
+#
+# This program 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 2 of the License, or
+# at your option) any later version.
+#
+# This program 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# Licensed under the GNU General Public License Version 2
+
+"""Regression test for the security issue CVE-2011-0725 tracked
+in LP #722228.
+
+Thanks to Sergey Nizovtsev for spotting this issue.
+
+The UpdateCache method allows to specify an alternative sources.list
+snippet to only update the repositories specified in the corresponding
+configuration file.
+
+Aptdaemon did not restrict the path to the sources.list.d directory and
+allowed to inject packages from malicious sources specified in a custom
+sources.list and even to read every file on the system.
+"""
+
+__author__ = "Michael Vogt <[email protected]>"
+
+import os
+import tempfile
+import time
+import unittest2
+
+import apt_pkg
+import dbus
+import mock
+
+import aptdaemon.client
+import aptdaemon.test
+from aptdaemon.worker import AptWorker
+from aptdaemon.errors import AptDaemonError
+
+
+class TestFix(unittest2.TestCase):
+
+ """Test the fix."""
+
+ def test_closed(self):
+ worker = AptWorker()
+ # We don't want to perform any cache changes
+ worker._cache = mock.Mock()
+ trans = mock.Mock()
+ # ensure normal operation keeps working
+ worker.update_cache(trans, None)
+ self.assertTrue(worker._cache.update.called)
+ worker._cache.reset_mock()
+ worker.update_cache(trans, "foobar.list")
+ self.assertTrue(worker._cache.update.called)
+ worker._cache.reset_mock()
+ worker.update_cache(trans, "/etc/apt/sources.list.d/foobar.list")
+ self.assertTrue(worker._cache.update.called)
+ worker._cache.reset_mock()
+ worker.update_cache(trans, "/etc/apt/sources.list")
+ self.assertTrue(worker._cache.update.called)
+
+ # ensure absolute path is no longer working
+ worker._cache.reset_mock()
+ self.assertRaises(AptDaemonError, worker.update_cache, trans,
+ "/etc/fstab")
+ self.assertFalse(worker._cache.update.called)
+ worker._cache.reset_mock()
+ self.assertRaises(AptDaemonError, worker.update_cache, trans,
+ "/tmp/etc/apt/sources.list.d")
+ self.assertFalse(worker._cache.update.called)
+ worker._cache.reset_mock()
+ self.assertRaises(AptDaemonError, worker.update_cache, trans,
+ "/etc/apt/sources.list.d/../../tmp/evil.list")
+ self.assertFalse(worker._cache.update.called)
+ worker._cache.reset_mock()
+ self.assertRaises(AptDaemonError, worker.update_cache, trans,
+ "../../../../../../../../../tmp/evil.list")
+ self.assertFalse(worker._cache.update.called)
+
+
+class TestExploit(aptdaemon.test.AptDaemonTestCase):
+
+ """Test if the a possible exploit still exists."""
+
+ def setUp(self):
+ """Setup a chroot, run the aptdaemon and a fake PolicyKit daemon."""
+ # Setup chroot
+ self.chroot = aptdaemon.test.Chroot()
+ self.chroot.setup()
+ self.addCleanup(self.chroot.remove)
+ # Start aptdaemon with the chroot on the session bus
+ self.start_dbus_daemon()
+ self.bus = dbus.bus.BusConnection(self.dbus_address)
+ self.start_session_aptd(self.chroot.path)
+ # Start the fake PolikcyKit daemon
+ self.start_fake_polkitd()
+ time.sleep(1)
+ # Create a file which containts a virtual secret
+ self.secrets_file = tempfile.NamedTemporaryFile(dir=self.chroot.path,
+ delete=False)
+ self.secrets_file.write("Oh oh!")
+ self.secrets_file.close()
+
+ @unittest2.expectedFailure
+ def test(self):
+ """A possible exploit of the security issue.
+ Originally provided by Sergey Nizovtsev.
+ """
+ repo_path = os.path.join(self.chroot.path, "repo")
+ lst_path = os.path.join(self.chroot.path, "malicious.list")
+
+ arch = apt_pkg.config["APT::Architecture"]
+
+ # Setup a pseudo repository and link the file which should be extracted
+ # to the Packages file
+ dir = os.path.join(repo_path, "dists/a/a/binary-%s" % arch)
+ os.makedirs(dir)
+ os.symlink(self.secrets_file.name, "%s/Packages" % dir)
+ # Create a malicious list file which injects the repo
+ with open(lst_path, "w") as lst_file:
+ lst_file.write("deb file://%s a a" % repo_path)
+
+ client = aptdaemon.client.AptClient(self.bus)
+ exit = client.update_cache(sources_list=lst_path, wait=True)
+ self.assertEqual(exit, aptdaemon.enums.EXIT_SUCCESS)
+
+ # Check if succeeded to leak the file content!
+ repo_path_encoded = apt_pkg.uri_to_filename("file://%s" % repo_path)
+ leaked_path = os.path.join(self.chroot.path, "var/lib/apt/lists/",
+ "%s_dists_a_a_binary-%s_"
+ "Packages" % (repo_path_encoded, arch))
+ with open(leaked_path, "r") as leaked_file:
+ self.assertEqual(leaked_file.read(), "Oh oh!")
+
+
+if __name__ == "__main__":
+ unittest2.main()
+
+# vim: ts=4 et sts=4
diff --git a/tests/regressions/test_lp768691.py b/tests/regressions/test_lp768691.py
new file mode 100644
index 0000000..14e5fe9
--- /dev/null
+++ b/tests/regressions/test_lp768691.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""Tests if we can handle different encodings well."""
+
+import locale
+import logging
+import os
+import sys
+import unittest
+
+from aptdaemon import core, enums, test, errors, utils
+
+DEBUG = True
+
+if sys.version >= '3':
+ unicode = str
+
+
+class GettextTest(test.AptDaemonTestCase):
+
+ """Regression test for LP: #768691 and LP: #926340
+
+ The gettext.translation.gettext() method returns a string in Python 2.
+ If we try to perform a string format operation, Python wants to convert
+ string to unicode. If the daemon is running with a different
+ default encoding as the translated message this results in an error.
+ By defaulf aptdaemon runs as C if activated by D-Bus.
+ """
+
+ def setUp(self):
+ # Use the mo files from the build
+ local_mo_files = os.path.join(test.get_tests_dir(),
+ "../build/mo")
+ if not os.path.isdir(local_mo_files):
+ self.skipTest("Please run setup.py build before since local mo "
+ "files are required. Run python setup.py build_i18n")
+ core.gettext._default_localedir = local_mo_files
+
+ self.trans = core.Transaction(None, enums.ROLE_FIX_BROKEN_DEPENDS,
+ None, os.getpid(), os.getuid(),
+ sys.argv[0], "org.debian.apt.test",
+ connect=False)
+ self.codes = utils.IsoCodes("iso_639", tag="iso_639_1_code",
+ fallback_tag="iso_639_2T_code")
+
+ def test(self):
+ """Test if the installation of an unauthenticated packages fails
+ if simulate hasn't been called explicitly before.
+ """
+ self.trans._set_locale("de_DE.UTF-8")
+ ret = self.trans.gettext("CD/DVD '%s' is required")
+ self.assertTrue(isinstance(ret, unicode))
+ error = errors.TransactionFailed(enums.ERROR_NO_PACKAGE,
+ "CD/DVD '%s' is required", "lala")
+ self.trans.error = error
+
+ utils.gettext._default_localedir = "/usr/share/locale"
+ lang = self.codes.get_localised_name("en", "ru.UTF-8")
+ self.assertTrue(isinstance(lang, unicode))
+
+if __name__ == "__main__":
+ if DEBUG:
+ logging.basicConfig(level=logging.DEBUG)
+ unittest.main()
+
+# vim: ts=4 et sts=4