From fce726023f703c369ae030684e75ed03c7544d6b Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 21 Dec 2007 13:56:19 +0100 Subject: implement AptAuthenticationReliabtlity spec --- test/pre-upload-check.py | 94 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 3 deletions(-) (limited to 'test/pre-upload-check.py') diff --git a/test/pre-upload-check.py b/test/pre-upload-check.py index 268b3d672..75a726808 100755 --- a/test/pre-upload-check.py +++ b/test/pre-upload-check.py @@ -4,6 +4,8 @@ import sys import os import glob import os.path +import shutil +import time from subprocess import call, PIPE import unittest @@ -11,7 +13,92 @@ import unittest stdout = os.open("/dev/null",0) #sys.stdout stderr = os.open("/dev/null",0) # sys.stderr -apt_args = [] # ["-o","Debug::pkgAcquire::Auth=true"] +apt_args = [] +#apt_args = ["-o","Debug::pkgAcquire::Auth=true"] + +class testAptAuthenticationReliability(unittest.TestCase): + """ + test if the spec https://wiki.ubuntu.com/AptAuthenticationReliability + is properly implemented + """ + apt = "../bin/apt-get" + + def setUp(self): + pass + def testRepositorySigFailure(self): + """ + test if a repository that used to be authenticated and fails on + apt-get update refuses to update and uses the old state + """ + # copy valid signatures into lists (those are ok, even + # if the name is "-broken-" ... + for f in glob.glob("./authReliability/lists/*"): + shutil.copy(f,"/var/lib/apt/lists") + # ensure we do *not* get a I-M-S hit + os.utime("/var/lib/apt/lists/%s" % os.path.basename(f), (0,0)) + res = call([self.apt, + "update", + "-o","Dir::Etc::sourcelist=./authReliability/sources.list.failure" + ] + apt_args, + stdout=stdout, stderr=stderr) + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Release.gpg"), + "The gpg file disappeared, this should not happen") + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Packages"), + "The Packages file disappeared, this should not happen") + # the same with i-m-s hit this time + for f in glob.glob("./authReliability/lists/*"): + shutil.copy(f,"/var/lib/apt/lists") + os.utime("/var/lib/apt/lists/%s" % os.path.basename(f), (time.time(),time.time())) + res = call([self.apt, + "update", + "-o","Dir::Etc::sourcelist=./authReliability/sources.list.failure" + ] + apt_args, + stdout=stdout, stderr=stderr) + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Release.gpg"), + "The gpg file disappeared, this should not happen") + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Packages"), + "The Packages file disappeared, this should not happen") + def testRepositorySigGood(self): + """ + test that a regular repository with good data stays good + """ + res = call([self.apt, + "update", + "-o","Dir::Etc::sourcelist=./authReliability/sources.list.good" + ] + apt_args, + stdout=stdout, stderr=stderr) + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Release.gpg"), + "The gpg file disappeared, this should not happen") + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Packages"), + "The Packages file disappeared, this should not happen") + # test good is still good after non I-M-S hit and a previous files in lists/ + for f in glob.glob("./authReliability/lists/*"): + shutil.copy(f,"/var/lib/apt/lists") + # ensure we do *not* get a I-M-S hit + os.utime("/var/lib/apt/lists/%s" % os.path.basename(f), (0,0)) + res = call([self.apt, + "update", + "-o","Dir::Etc::sourcelist=./authReliability/sources.list.good" + ] + apt_args, + stdout=stdout, stderr=stderr) + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Release.gpg"), + "The gpg file disappeared, this should not happen") + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Packages"), + "The Packages file disappeared, this should not happen") + # test good is still good after I-M-S hit + for f in glob.glob("./authReliability/lists/*"): + shutil.copy(f,"/var/lib/apt/lists") + # ensure we do get a I-M-S hit + os.utime("/var/lib/apt/lists/%s" % os.path.basename(f), (time.time(),time.time())) + res = call([self.apt, + "update", + "-o","Dir::Etc::sourcelist=./authReliability/sources.list.good" + ] + apt_args, + stdout=stdout, stderr=stderr) + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Release.gpg"), + "The gpg file disappeared, this should not happen") + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Packages"), + "The Packages file disappeared, this should not happen") class testAuthentication(unittest.TestCase): @@ -149,6 +236,7 @@ if __name__ == "__main__": if len(sys.argv) > 1 and sys.argv[1] == "-v": stdout = sys.stdout stderr = sys.stderr + + # run only one for now + #unittest.main(defaultTest="testAptAuthenticationReliability") unittest.main() - - -- cgit v1.2.3-70-g09d2 From f3224a73ec718a5f4e4404cd716e4b7c2702bb8b Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 2 Jan 2008 13:50:56 +0100 Subject: test/authReliability/sources.list.good: - add missing file to make the test/pre-upload-check.py work again apt-pkg/acquire-item.cc: - fix auth-reliable code when file:// uris are used test/pre-upload-check.py: - use the standard apt, not "../bin/apt-get" by default - make the error messages more useful on test-failure --- apt-pkg/acquire-item.cc | 4 ++++ test/authReliability/sources.list.good | 2 ++ test/pre-upload-check.py | 7 ++++--- 3 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 test/authReliability/sources.list.good (limited to 'test/pre-upload-check.py') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 54526ab05..fa48eeae9 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -935,6 +935,9 @@ void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string Hash, else { RetrievalDone(Message); + if (!Complete) + // Still more retrieving to do + return; if (SigFile == "") { @@ -987,6 +990,7 @@ void pkgAcqMetaIndex::RetrievalDone(string Message) FinalFile += URItoFileName(RealURI); DestFile = FinalFile; } + Complete = true; } void pkgAcqMetaIndex::AuthDone(string Message) diff --git a/test/authReliability/sources.list.good b/test/authReliability/sources.list.good new file mode 100644 index 000000000..2e9a4458a --- /dev/null +++ b/test/authReliability/sources.list.good @@ -0,0 +1,2 @@ +deb http://people.ubuntu.com/~mvo/apt/auth-test-suit/gpg-package-ok/ / + diff --git a/test/pre-upload-check.py b/test/pre-upload-check.py index 75a726808..ca44ec726 100755 --- a/test/pre-upload-check.py +++ b/test/pre-upload-check.py @@ -21,7 +21,8 @@ class testAptAuthenticationReliability(unittest.TestCase): test if the spec https://wiki.ubuntu.com/AptAuthenticationReliability is properly implemented """ - apt = "../bin/apt-get" + #apt = "../bin/apt-get" + apt = "apt-get" def setUp(self): pass @@ -68,7 +69,7 @@ class testAptAuthenticationReliability(unittest.TestCase): ] + apt_args, stdout=stdout, stderr=stderr) self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Release.gpg"), - "The gpg file disappeared, this should not happen") + "The gpg file disappeared after a regular download, this should not happen") self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Packages"), "The Packages file disappeared, this should not happen") # test good is still good after non I-M-S hit and a previous files in lists/ @@ -82,7 +83,7 @@ class testAptAuthenticationReliability(unittest.TestCase): ] + apt_args, stdout=stdout, stderr=stderr) self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Release.gpg"), - "The gpg file disappeared, this should not happen") + "The gpg file disappeared after a I-M-S hit, this should not happen") self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Packages"), "The Packages file disappeared, this should not happen") # test good is still good after I-M-S hit -- cgit v1.2.3-70-g09d2 From 5d149bfc7f34bc39e0edf8d9d98786cadefeeedf Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 4 Feb 2008 14:15:17 +0100 Subject: add APT::Update::Auth-Failure script --- apt-pkg/acquire-item.cc | 1 + test/pre-upload-check.py | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'test/pre-upload-check.py') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index ad48adcff..a00b0b6d3 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1179,6 +1179,7 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) "GPG error: %s: %s\n"), Desc.Description.c_str(), LookupTag(Message,"Message").c_str()); + RunScripts("APT::Update::Auth-Failure"); return; } else { _error->Warning(_("GPG error: %s: %s"), diff --git a/test/pre-upload-check.py b/test/pre-upload-check.py index ca44ec726..de43122ce 100755 --- a/test/pre-upload-check.py +++ b/test/pre-upload-check.py @@ -25,7 +25,8 @@ class testAptAuthenticationReliability(unittest.TestCase): apt = "apt-get" def setUp(self): - pass + if os.path.exists("/tmp/autFailure"): + os.unlink("/tmp/authFailure"); def testRepositorySigFailure(self): """ test if a repository that used to be authenticated and fails on @@ -39,26 +40,33 @@ class testAptAuthenticationReliability(unittest.TestCase): os.utime("/var/lib/apt/lists/%s" % os.path.basename(f), (0,0)) res = call([self.apt, "update", - "-o","Dir::Etc::sourcelist=./authReliability/sources.list.failure" + "-o","Dir::Etc::sourcelist=./authReliability/sources.list.failure", + "-o",'APT::Update::Auth-Failure::=touch /tmp/authFailure', ] + apt_args, stdout=stdout, stderr=stderr) self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Release.gpg"), "The gpg file disappeared, this should not happen") self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Packages"), "The Packages file disappeared, this should not happen") + self.assert_(os.path.exists("/tmp/authFailure"), + "The APT::Update::Auth-Failure script did not run") + os.unlink("/tmp/authFailure"); # the same with i-m-s hit this time for f in glob.glob("./authReliability/lists/*"): shutil.copy(f,"/var/lib/apt/lists") os.utime("/var/lib/apt/lists/%s" % os.path.basename(f), (time.time(),time.time())) res = call([self.apt, "update", - "-o","Dir::Etc::sourcelist=./authReliability/sources.list.failure" + "-o","Dir::Etc::sourcelist=./authReliability/sources.list.failure", + "-o",'APT::Update::Auth-Failure::=touch /tmp/authFailure', ] + apt_args, stdout=stdout, stderr=stderr) self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Release.gpg"), "The gpg file disappeared, this should not happen") self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Packages"), "The Packages file disappeared, this should not happen") + self.assert_(os.path.exists("/tmp/authFailure"), + "The APT::Update::Auth-Failure script did not run") def testRepositorySigGood(self): """ test that a regular repository with good data stays good @@ -239,5 +247,5 @@ if __name__ == "__main__": stderr = sys.stderr # run only one for now - #unittest.main(defaultTest="testAptAuthenticationReliability") - unittest.main() + unittest.main(defaultTest="testAptAuthenticationReliability") + #unittest.main() -- cgit v1.2.3-70-g09d2 From d54385388a0773fada9e44c5d1cf020488047884 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 8 Feb 2008 14:30:39 +0100 Subject: make the test-suit more reliable --- test/pre-upload-check.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'test/pre-upload-check.py') diff --git a/test/pre-upload-check.py b/test/pre-upload-check.py index de43122ce..9c2e1916c 100755 --- a/test/pre-upload-check.py +++ b/test/pre-upload-check.py @@ -27,6 +27,8 @@ class testAptAuthenticationReliability(unittest.TestCase): def setUp(self): if os.path.exists("/tmp/autFailure"): os.unlink("/tmp/authFailure"); + if os.path.exists("/tmp/autFailure2"): + os.unlink("/tmp/authFailure2"); def testRepositorySigFailure(self): """ test if a repository that used to be authenticated and fails on @@ -49,8 +51,7 @@ class testAptAuthenticationReliability(unittest.TestCase): self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Packages"), "The Packages file disappeared, this should not happen") self.assert_(os.path.exists("/tmp/authFailure"), - "The APT::Update::Auth-Failure script did not run") - os.unlink("/tmp/authFailure"); + "The APT::Update::Auth-Failure script did not run (1)") # the same with i-m-s hit this time for f in glob.glob("./authReliability/lists/*"): shutil.copy(f,"/var/lib/apt/lists") @@ -58,15 +59,15 @@ class testAptAuthenticationReliability(unittest.TestCase): res = call([self.apt, "update", "-o","Dir::Etc::sourcelist=./authReliability/sources.list.failure", - "-o",'APT::Update::Auth-Failure::=touch /tmp/authFailure', + "-o",'APT::Update::Auth-Failure::=touch /tmp/authFailure2', ] + apt_args, stdout=stdout, stderr=stderr) self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Release.gpg"), "The gpg file disappeared, this should not happen") self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Packages"), "The Packages file disappeared, this should not happen") - self.assert_(os.path.exists("/tmp/authFailure"), - "The APT::Update::Auth-Failure script did not run") + self.assert_(os.path.exists("/tmp/authFailure2"), + "The APT::Update::Auth-Failure script did not run (2)") def testRepositorySigGood(self): """ test that a regular repository with good data stays good -- cgit v1.2.3-70-g09d2 From 1ddb859611d2e0f3d9ea12085001810f689e8c99 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 8 Jun 2010 19:27:49 +0200 Subject: * apt-pkg/indexrecords.cc: - backport forgotten Valid-Until patch from the obsolete experimental branch to prevent replay attacks better, thanks to Thomas Viehmann for the initial patch! (Closes: #499897) --- apt-pkg/acquire-item.cc | 12 ++++++- apt-pkg/indexrecords.cc | 38 ++++++++++++++++++++-- apt-pkg/indexrecords.h | 4 +++ debian/changelog | 4 +++ test/pre-upload-check.py | 14 ++++++++ .../sources.list.all-validuntil-broken | 1 + 6 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 test/testsources.list/sources.list.all-validuntil-broken (limited to 'test/pre-upload-check.py') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index c035b9163..4a846804e 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -33,6 +33,7 @@ #include #include #include +#include /*}}}*/ using namespace std; @@ -1177,6 +1178,15 @@ bool pkgAcqMetaIndex::VerifyVendor(string Message) /*{{{*/ Transformed = ""; } + if (_config->FindB("Acquire::Check-Valid-Until", true)) { + if (MetaIndexParser->GetValidUntil() > 0 && + time(NULL) > MetaIndexParser->GetValidUntil()) { + return _error->Error(_("Release file expired, ignoring %s (valid until %s)"), + RealURI.c_str(), + TimeRFC1123(MetaIndexParser->GetValidUntil()).c_str()); + } + } + if (_config->FindB("Debug::pkgAcquire::Auth", false)) { std::cerr << "Got Codename: " << MetaIndexParser->GetDist() << std::endl; @@ -1194,7 +1204,7 @@ bool pkgAcqMetaIndex::VerifyVendor(string Message) /*{{{*/ // return false; if (!Transformed.empty()) { - _error->Warning("Conflicting distribution: %s (expected %s but got %s)", + _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"), Desc.Description.c_str(), Transformed.c_str(), MetaIndexParser->GetDist().c_str()); diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index 1fc27b1a1..24ed02ba5 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -7,8 +7,11 @@ #include #include #include +#include #include #include +#include + /*}}}*/ string indexRecords::GetDist() const { @@ -26,6 +29,11 @@ string indexRecords::GetExpectedDist() const return this->ExpectedDist; } +time_t indexRecords::GetValidUntil() const +{ + return this->ValidUntil; +} + const indexRecords::checkSum *indexRecords::Lookup(const string MetaKey) { return Entries[MetaKey]; @@ -82,7 +90,33 @@ bool indexRecords::Load(const string Filename) /*{{{*/ return false; } - string Strdate = Section.FindS("Date"); // FIXME: verify this somehow? + string Label = Section.FindS("Label"); + string StrDate = Section.FindS("Date"); + string StrValidUntil = Section.FindS("Valid-Until"); + + // if we have a Valid-Until header, use it + if (!StrValidUntil.empty()) + { + // set ValidUntil based on the information in the Release file + if(!StrToTime(StrValidUntil, ValidUntil)) + { + ErrorText = _(("Invalid 'Valid-Until' entry in Release file " + Filename).c_str()); + return false; + } + } else { + // if we don't have a valid-until string, check if we have a default + if (!Label.empty()) + { + int MaxAge = _config->FindI(string("apt::acquire::max-default-age::"+Label).c_str(),0); + if(MaxAge > 0 && !StrToTime(StrDate, ValidUntil)) + { + ErrorText = _(("Invalid 'Date' entry in Release file " + Filename).c_str()); + return false; + } + ValidUntil += 24*60*60*MaxAge; + } + } + return true; } /*}}}*/ @@ -160,6 +194,6 @@ indexRecords::indexRecords() } indexRecords::indexRecords(const string ExpectedDist) : - ExpectedDist(ExpectedDist) + ExpectedDist(ExpectedDist), ValidUntil(0) { } diff --git a/apt-pkg/indexrecords.h b/apt-pkg/indexrecords.h index 468d2bd0f..500cf23c4 100644 --- a/apt-pkg/indexrecords.h +++ b/apt-pkg/indexrecords.h @@ -12,6 +12,7 @@ #include #include +#include class indexRecords { @@ -25,6 +26,8 @@ class indexRecords string Dist; string Suite; string ExpectedDist; + time_t ValidUntil; + std::map Entries; public: @@ -38,6 +41,7 @@ class indexRecords virtual bool Load(string Filename); string GetDist() const; + time_t GetValidUntil() const; virtual bool CheckDist(const string MaybeDist) const; string GetExpectedDist() const; virtual ~indexRecords(){}; diff --git a/debian/changelog b/debian/changelog index 3771ca415..d8fb57757 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,10 @@ apt (0.7.26~exp5) experimental; urgency=low [ David Kalnischkies ] + * apt-pkg/indexrecords.cc: + - backport forgotten Valid-Until patch from the obsolete experimental + branch to prevent replay attacks better, thanks to Thomas Viehmann + for the initial patch! (Closes: #499897) * cmdline/apt-get.cc: - rerun dpkg-source in source if --fix-broken is given (Closes: #576752) - don't suggest held packages as they are installed (Closes: #578135) diff --git a/test/pre-upload-check.py b/test/pre-upload-check.py index 268b3d672..e2dfecbd3 100755 --- a/test/pre-upload-check.py +++ b/test/pre-upload-check.py @@ -95,6 +95,20 @@ class testAuthentication(unittest.TestCase): self.assert_(len(glob.glob("/var/lib/apt/lists/partial/*")) == 0, "partial/ dir has leftover files: %s" % glob.glob("/var/lib/apt/lists/partial/*")) + def testValid(self): + for f in glob.glob("testsources.list/sources.list*validuntil*"): + self._cleanup() + (prefix, testtype, result) = f.split("-") + expected_res = self._expectedRes(result) + cmd = ["update"] + res = call([self.apt,"-o","Dir::Etc::sourcelist=./%s" % f]+cmd+apt_args, + stdout=stdout, stderr=stderr) + self.assert_(res == expected_res, + "test '%s' failed (got %s expected %s" % (f,res,expected_res)) + if expected_res == 0: + self.assert_(len(glob.glob("/var/lib/apt/lists/partial/*")) == 0, + "partial/ dir has leftover files: %s" % glob.glob("/var/lib/apt/lists/partial/*")) + class testLocalRepositories(unittest.TestCase): " test local repository regressions " diff --git a/test/testsources.list/sources.list.all-validuntil-broken b/test/testsources.list/sources.list.all-validuntil-broken new file mode 100644 index 000000000..bab59bb81 --- /dev/null +++ b/test/testsources.list/sources.list.all-validuntil-broken @@ -0,0 +1 @@ +deb http://people.ubuntu.com/~mvo/apt/auth-test-suit/all-validuntil-broken/ / -- cgit v1.2.3-70-g09d2