From c9c910695185b59aa27b787c1a250497e47b492b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 6 Aug 2016 19:59:57 +0200 Subject: allow methods to be disabled and redirected via config To prevent accidents like adding http-sources while using tor+http it can make sense to allow disabling methods. It might even make sense to allow "redirections" and adding "symlinked" methods via configuration. This could e.g. allow using different options for certain sources by adding and configuring a "virtual" new method which picks up the config based on the name it was called with like e.g. http does if called as tor+http. --- apt-pkg/acquire-worker.cc | 31 +++++++++++++++++----- test/integration/test-apt-https-no-redirect | 15 +++++++++++ .../test-apt-update-failure-propagation | 21 ++++++++++----- test/integration/test-bug-738785-switch-protocol | 20 ++------------ .../test-different-methods-for-same-source | 15 ++--------- 5 files changed, 58 insertions(+), 44 deletions(-) diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 1ee78d070..7a4f8177f 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -93,9 +93,22 @@ pkgAcquire::Worker::~Worker() bool pkgAcquire::Worker::Start() { // Get the method path - string Method = _config->FindDir("Dir::Bin::Methods") + Access; + constexpr char const * const methodsDir = "Dir::Bin::Methods"; + std::string const confItem = std::string(methodsDir) + "::" + Access; + std::string Method; + if (_config->Exists(confItem)) + Method = _config->FindFile(confItem.c_str()); + else + Method = _config->FindDir(methodsDir) + Access; if (FileExists(Method) == false) { + if (flNotDir(Method) == "false") + { + _error->Error(_("The method '%s' is explicitly disabled via configuration."), Access.c_str()); + if (Access == "http" || Access == "https") + _error->Notice(_("If you meant to use Tor remember to use %s instead of %s."), ("tor+" + Access).c_str(), Access.c_str()); + return false; + } _error->Error(_("The method driver %s could not be found."),Method.c_str()); std::string const A(Access.cbegin(), std::find(Access.cbegin(), Access.cend(), '+')); std::string pkg; @@ -103,9 +116,15 @@ bool pkgAcquire::Worker::Start() _error->Notice(_("Is the package %s installed?"), pkg.c_str()); return false; } + std::string const Calling = _config->FindDir(methodsDir) + Access; if (Debug == true) - clog << "Starting method '" << Method << '\'' << endl; + { + std::clog << "Starting method '" << Calling << "'"; + if (Calling != Method) + std::clog << " ( via " << Method << " )"; + std::clog << endl; + } // Create the pipes int Pipes[4] = {-1,-1,-1,-1}; @@ -130,11 +149,9 @@ bool pkgAcquire::Worker::Start() SetCloseExec(STDIN_FILENO,false); SetCloseExec(STDERR_FILENO,false); - const char *Args[2]; - Args[0] = Method.c_str(); - Args[1] = 0; - execv(Args[0],(char **)Args); - cerr << "Failed to exec method " << Args[0] << endl; + const char * const Args[] = { Calling.c_str(), nullptr }; + execv(Method.c_str() ,const_cast(Args)); + std::cerr << "Failed to exec method " << Calling << " ( via " << Method << ")" << endl; _exit(100); } diff --git a/test/integration/test-apt-https-no-redirect b/test/integration/test-apt-https-no-redirect index 69e2ba57f..d6c630d5f 100755 --- a/test/integration/test-apt-https-no-redirect +++ b/test/integration/test-apt-https-no-redirect @@ -14,6 +14,7 @@ echo 'alright' > aptarchive/working changetohttpswebserver webserverconfig 'aptwebserver::redirect::replace::/redirectme/' "http://localhost:${APTHTTPPORT}/" webserverconfig 'aptwebserver::redirect::replace::/redirectme2/' "https://localhost:${APTHTTPSPORT}/" +echo 'Dir::Bin::Methods::https+http "https";' > rootdir/etc/apt/apt.conf.d/99add-https-http-method msgtest 'download of a file works via' 'http' testsuccess --nomsg downloadfile "http://localhost:${APTHTTPPORT}/working" httpfile @@ -22,9 +23,23 @@ testfileequal httpfile 'alright' msgtest 'download of a file works via' 'https' testsuccess --nomsg downloadfile "https://localhost:${APTHTTPSPORT}/working" httpsfile testfileequal httpsfile 'alright' +rm -f httpfile httpsfile + +msgtest 'download of http file works via' 'https+http' +testsuccess --nomsg downloadfile "http://localhost:${APTHTTPPORT}/working" httpfile +testfileequal httpfile 'alright' + +msgtest 'download of https file works via' 'https+http' +testsuccess --nomsg downloadfile "https://localhost:${APTHTTPSPORT}/working" httpsfile +testfileequal httpsfile 'alright' +rm -f httpfile httpsfile msgtest 'download of a file does not work if' 'https redirected to http' testfailure --nomsg downloadfile "https://localhost:${APTHTTPSPORT}/redirectme/working" redirectfile msgtest 'libcurl has forbidden access in last request to' 'http resource' testsuccess --nomsg grep -q -E -- "Redirection from https to 'http://.*' is forbidden" rootdir/tmp/testfailure.output + +msgtest 'download of a file does work if' 'https+http redirected to https' +testsuccess --nomsg downloadfile "https+http://localhost:${APTHTTPPORT}/redirectme2/working" redirectfile +testfileequal redirectfile 'alright' diff --git a/test/integration/test-apt-update-failure-propagation b/test/integration/test-apt-update-failure-propagation index ec6bf4a48..1361b1b93 100755 --- a/test/integration/test-apt-update-failure-propagation +++ b/test/integration/test-apt-update-failure-propagation @@ -27,10 +27,11 @@ for FILE in rootdir/etc/apt/sources.list.d/*-sid-* ; do done pretest() { + msgmsg "$@" rm -rf rootdir/var/lib/apt/lists testsuccessequal 'N: Unable to locate package foo' aptcache policy foo } -pretest +pretest 'initialize test' 'update' testsuccess aptget update testsuccessequal "foo: Installed: (none) @@ -41,7 +42,7 @@ testsuccessequal "foo: 1 500 500 https://localhost:${APTHTTPSPORT} stable/main all Packages" aptcache policy foo -pretest +pretest 'not found' 'release files' mv aptarchive/dists/stable aptarchive/dists/stable.good testfailuremsg "E: The repository 'https://localhost:${APTHTTPSPORT} stable Release' does not have a Release file. N: Updating from such a repository can't be done securely, and is therefore disabled by default. @@ -76,7 +77,16 @@ posttest() { } posttest -pretest +pretest 'method disabled' 'https' +echo 'Dir::Bin::Methods::https "false";' > rootdir/etc/apt/apt.conf.d/99disable-https +testfailuremsg "E: The method 'https' is explicitly disabled via configuration. +N: If you meant to use Tor remember to use tor+https instead of https. +E: Failed to fetch https://localhost:${APTHTTPSPORT}/dists/stable/InRelease +E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update +rm -f rootdir/etc/apt/apt.conf.d/99disable-https +posttest + +pretest 'method not installed' 'https' rm "${NEWMETHODS}/https" testfailuremsg "E: The method driver ${TMPWORKINGDIRECTORY}/rootdir/usr/lib/apt/methods/https could not be found. N: Is the package apt-transport-https installed? @@ -84,13 +94,12 @@ E: Failed to fetch https://localhost:${APTHTTPSPORT}/dists/stable/InRelease E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update posttest -ln -s "$OLDMETHODS/https" "$NEWMETHODS" -pretest +pretest 'https connection refused' 'doom port' for FILE in rootdir/etc/apt/sources.list.d/*-stable-* ; do # lets see how many testservers run also Doom sed -i -e "s#:${APTHTTPSPORT}/#:666/#" "$FILE" done -testwarning aptget update +testwarning aptget update -o Dir::Bin::Methods::https="${OLDMETHODS}/https" testequalor2 "W: Failed to fetch https://localhost:666/dists/stable/InRelease Failed to connect to localhost port 666: Connection refused W: Some index files failed to download. They have been ignored, or old ones used instead." "W: Failed to fetch https://localhost:666/dists/stable/InRelease couldn't connect to host W: Some index files failed to download. They have been ignored, or old ones used instead." tail -n 2 rootdir/tmp/testwarning.output diff --git a/test/integration/test-bug-738785-switch-protocol b/test/integration/test-bug-738785-switch-protocol index fa6702eb0..690e8727e 100755 --- a/test/integration/test-bug-738785-switch-protocol +++ b/test/integration/test-bug-738785-switch-protocol @@ -38,28 +38,12 @@ cd - >/dev/null testsuccess aptget install apt -y testdpkginstalled 'apt' -# install a slowed down file: otherwise its to fast to reproduce combining -NEWMETHODS="$(readlink -f rootdir)/usr/lib/apt/methods" -OLDMETHODS="$(readlink -f rootdir/usr/lib/apt/methods)" -rm "$NEWMETHODS" -mkdir "$NEWMETHODS" -backupIFS="$IFS" -IFS="$(printf "\n\b")" -for METH in $(find "$OLDMETHODS" -maxdepth 1 ! -type d); do - ln -s "$OLDMETHODS/$(basename "$METH")" "$NEWMETHODS" -done -IFS="$backupIFS" -rm "$NEWMETHODS/https" - cd downloaded -testfailureequal "E: The method driver $(readlink -f './../')/rootdir/usr/lib/apt/methods/https could not be found. -N: Is the package apt-transport-https installed?" aptget download apt +testfailureequal "E: The method 'https' is explicitly disabled via configuration. +N: If you meant to use Tor remember to use tor+https instead of https." aptget download apt -o Dir::Bin::Methods::https=false testfailure test -e apt_1.0_all.deb cd - >/dev/null -# revert to all methods -ln -s "$OLDMETHODS/https" "$NEWMETHODS" - # check that downgrades from https to http are not allowed webserverconfig 'aptwebserver::support::http' 'true' sed -i -e "s#:${APTHTTPPORT}/redirectme#:${APTHTTPSPORT}/downgrademe#" -e 's# http:# https:#' rootdir/etc/apt/sources.list.d/* diff --git a/test/integration/test-different-methods-for-same-source b/test/integration/test-different-methods-for-same-source index 40138ad5d..791a84cb7 100755 --- a/test/integration/test-different-methods-for-same-source +++ b/test/integration/test-different-methods-for-same-source @@ -10,21 +10,10 @@ insertpackage 'stable' 'foo' 'all' '1' insertsource 'stable' 'foo' 'all' '1' setupaptarchive --no-update -# install a slowed down file: otherwise its to fast to reproduce combining -NEWMETHODS="$(readlink -f rootdir)/usr/lib/apt/methods" -OLDMETHODS="$(readlink -f rootdir/usr/lib/apt/methods)" -rm "$NEWMETHODS" -mkdir "$NEWMETHODS" -backupIFS="$IFS" -IFS="$(printf "\n\b")" -for METH in $(find "$OLDMETHODS" -maxdepth 1 ! -type d); do - ln -s "$OLDMETHODS/$(basename "$METH")" "$NEWMETHODS" -done -IFS="$backupIFS" -ln -s "${OLDMETHODS}/http" "${NEWMETHODS}/http-ng" - changetowebserver webserverconfig 'aptwebserver::redirect::replace::/redirectme/' "http://localhost:${APTHTTPPORT}/" + +echo 'Dir::Bin::Methods::http-ng "http";' > rootdir/etc/apt/apt.conf.d/99add-http-ng-method sed -i -e 's# http:# http-ng:#' $(find rootdir/etc/apt/sources.list.d -name '*-deb-src.list') testsuccess apt update -o Debug::Acquire::http-ng=1 -- cgit v1.2.3