summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apt-pkg/acquire-item.cc45
-rwxr-xr-xtest/integration/test-cve-2018-0501-mirror-alternatives31
-rwxr-xr-xtest/integration/test-method-mirror12
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