diff options
-rw-r--r-- | apt-pkg/acquire-item.cc | 45 | ||||
-rwxr-xr-x | test/integration/test-cve-2018-0501-mirror-alternatives | 31 | ||||
-rwxr-xr-x | test/integration/test-method-mirror | 12 |
3 files changed, 67 insertions, 21 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index b40c67ec1..83c793093 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -277,6 +277,27 @@ static HashStringList GetExpectedHashesFromFor(metaIndex * const Parser, std::st } /*}}}*/ +class pkgAcquire::Item::Private /*{{{*/ +{ +public: + struct AlternateURI + { + std::string URI; + std::unordered_map<std::string, std::string> changefields; + AlternateURI(std::string &&u, decltype(changefields) &&cf) : URI(u), changefields(cf) {} + }; + std::list<AlternateURI> AlternativeURIs; + std::vector<std::string> BadAlternativeSites; + std::vector<std::string> PastRedirections; + std::unordered_map<std::string, std::string> CustomFields; + unsigned int Retries; + + Private() : Retries(_config->FindI("Acquire::Retries", 0)) + { + } +}; + /*}}}*/ + // all ::HashesRequired and ::GetExpectedHashes implementations /*{{{*/ /* ::GetExpectedHashes is abstract and has to be implemented by all subclasses. It is best to implement it as broadly as possible, while ::HashesRequired defaults @@ -748,25 +769,6 @@ class APT_HIDDEN CleanupItem : public pkgAcqTransactionItem /*{{{*/ /*}}}*/ // Acquire::Item::Item - Constructor /*{{{*/ -class pkgAcquire::Item::Private -{ -public: - struct AlternateURI - { - std::string URI; - std::unordered_map<std::string, std::string> changefields; - AlternateURI(std::string &&u, decltype(changefields) &&cf) : URI(u), changefields(cf) {} - }; - std::list<AlternateURI> AlternativeURIs; - std::vector<std::string> BadAlternativeSites; - std::vector<std::string> PastRedirections; - std::unordered_map<std::string, std::string> CustomFields; - unsigned int Retries; - - Private() : Retries(_config->FindI("Acquire::Retries", 0)) - { - } -}; APT_IGNORE_DEPRECATED_PUSH pkgAcquire::Item::Item(pkgAcquire * const owner) : FileSize(0), PartialSize(0), Mode(0), ID(0), Complete(false), Local(false), @@ -1045,7 +1047,7 @@ void pkgAcquire::Item::Done(string const &/*Message*/, HashStringList const &Has } Status = StatDone; ErrorText.clear(); - Owner->Dequeue(this); + Dequeue(); } /*}}}*/ // Acquire::Item::Rename - Rename a file /*{{{*/ @@ -1070,6 +1072,7 @@ bool pkgAcquire::Item::Rename(string const &From,string const &To) /*}}}*/ void pkgAcquire::Item::Dequeue() /*{{{*/ { + d->AlternativeURIs.clear(); Owner->Dequeue(this); } /*}}}*/ @@ -1272,7 +1275,7 @@ void pkgAcqMetaBase::AbortTransaction() { (*I)->ExpectedAdditionalItems = 0; if ((*I)->Status != pkgAcquire::Item::StatFetching) - Owner->Dequeue(*I); + (*I)->Dequeue(); (*I)->TransactionState(TransactionAbort); } Transaction.clear(); diff --git a/test/integration/test-cve-2018-0501-mirror-alternatives b/test/integration/test-cve-2018-0501-mirror-alternatives new file mode 100755 index 000000000..f15454765 --- /dev/null +++ b/test/integration/test-cve-2018-0501-mirror-alternatives @@ -0,0 +1,31 @@ +#!/bin/sh +set -e +TESTDIR="$(readlink -f "$(dirname "$0")")" +. "$TESTDIR/framework" + +setupenvironment +configarchitecture "i386" + +buildsimplenativepackage 'foo' 'all' '1' 'stable' +setupaptarchive --no-update +changetohttpswebserver + +# User has mirror method configured in apt >= 1.6~alpha6 & +# Eve has enough MITM control over the network to +# a) have the mirror file include at least two mirrors and +# b) can send her bad InRelease files for both mirrors +sed -i -e 's# https:# mirror+https:#' -e 's#/ stable#/mirror.txt stable#' rootdir/etc/apt/sources.list.d/*-stable-* +echo "http://localhost:${APTHTTPPORT} +https://localhost:${APTHTTPSPORT}" > aptarchive/mirror.txt + +# real Eve would do something worse… +sed -i "/^Date: / a\ +Evil: yes" $(find ./aptarchive -name 'Release' -o -name 'InRelease') + +# progress display shows that the InRelease file was bad, +# but it is used anyhow as the bad file causes a fallback to +# a request to the second mirror which completes successful +# causing apt to believe the verify completed successfully… +testfailure apt update +testfailure grep '^Evil:' rootdir/var/lib/apt/lists/*Release +testfailure apt show foo diff --git a/test/integration/test-method-mirror b/test/integration/test-method-mirror index 38d6be9a9..56c9a10a0 100755 --- a/test/integration/test-method-mirror +++ b/test/integration/test-method-mirror @@ -196,6 +196,7 @@ msgmsg 'The prefix for the mirrorlist is' 'passed on' echo 'Dir::Bin::Methods::foo+mirror+file "mirror"; Dir::Bin::Methods::foo+mirror+http "mirror"; Dir::Bin::Methods::foo+http "http"; +Dir::Bin::Methods::foo+https "https"; ' > rootdir/etc/apt/apt.conf.d/99add-foo-method echo "http://localhost:${APTHTTPPORT}/redirectme " > aptarchive/mirror.txt @@ -241,3 +242,14 @@ Building dependency tree... Reading state information... All packages are up to date." apt update testrundownload 'foo=2' + +echo "https://localhost:${APTHTTPSPORT}/ +http://localhost:${APTHTTPPORT}/redirectme" > aptarchive/mirror.txt +rm -rf rootdir/var/lib/apt/lists +sed -i -e "s# foo+# [signed-by=$(readlink -f ./keys/joesixpack.pub)] foo+#g" rootdir/etc/apt/sources.list.d/apt-test-unstable-deb* +testsuccess apt update +testrundownload 'foo=2' + +rm -rf rootdir/var/lib/apt/lists +sed -i -e "s# \[signed-by=[^]]\+\] foo+# [signed-by=$(readlink -f ./keys/marvinparanoid.pub)] foo+#g" rootdir/etc/apt/sources.list.d/apt-test-unstable-deb* +testfailure apt update |