From 4df5483994d510290677abab5720445f71babe65 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 18 Nov 2017 12:38:21 +0100 Subject: non-local mirrorlists shouldn't redirect to local A mirror list we get from an non-local source like http shouldn't be able to include e.g. file sources and even with other online sources we need to be careful: They also shouldn't include prefixed methods like 'tor+http'. So apply magic based on how the method is called: mirror+file will be allowed to redirect to any source while tor+mirror+file allows all, but sends them to their tor+ variant. --- methods/CMakeLists.txt | 2 +- methods/mirror.cc | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/methods/CMakeLists.txt b/methods/CMakeLists.txt index cf5ab799d..c4a32b4f5 100644 --- a/methods/CMakeLists.txt +++ b/methods/CMakeLists.txt @@ -26,7 +26,7 @@ target_link_libraries(ftp ${GNUTLS_LIBRARIES}) install(TARGETS file copy store gpgv cdrom http ftp rred rsh mirror RUNTIME DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/apt/methods) -add_slaves(${CMAKE_INSTALL_LIBEXECDIR}/apt/methods mirror mirror+http mirror+https mirror+file) +add_slaves(${CMAKE_INSTALL_LIBEXECDIR}/apt/methods mirror mirror+ftp mirror+http mirror+https mirror+file mirror+copy) add_slaves(${CMAKE_INSTALL_LIBEXECDIR}/apt/methods rsh ssh) diff --git a/methods/mirror.cc b/methods/mirror.cc index 4b9cd7384..add9f0875 100644 --- a/methods/mirror.cc +++ b/methods/mirror.cc @@ -28,6 +28,7 @@ #include /*}}}*/ +constexpr char const *const disallowLocal[] = {"ftp", "http", "https"}; static void sortByLength(std::vector &vec) /*{{{*/ { @@ -204,17 +205,47 @@ bool MirrorMethod::MirrorListFileRecieved(MirrorListInfo &info, FetchItem *const FileFd mirrorlist; if (FileExists(Itm->DestFile) && mirrorlist.Open(Itm->DestFile, FileFd::ReadOnly, FileFd::Extension)) { + auto const accessColon = info.baseuri.find(':'); + auto access = info.baseuri.substr(0, accessColon); + std::string prefixAccess; + if (APT::String::Startswith(access, "mirror") == false) + { + auto const plus = info.baseuri.find('+'); + prefixAccess = info.baseuri.substr(0, plus); + access.erase(0, plus + 1); + } + std::vector limitAccess; + // If the mirror file comes from an online source, allow only other online + // sources, not e.g. file:///. If the mirrorlist comes from there we can assume + // the admin knows what (s)he is doing through and not limit the options. + if (std::any_of(std::begin(disallowLocal), std::end(disallowLocal), + [&access](char const *const a) { return APT::String::Endswith(access, std::string("+") + a); }) || + access == "mirror") + { + for (auto const &a : disallowLocal) + limitAccess.emplace_back(a); + } std::string line; while (mirrorlist.ReadLine(line)) { if (line.empty() || line[0] == '#') continue; + auto const access = line.substr(0, line.find(':')); + if (limitAccess.empty() == false && std::find(limitAccess.begin(), limitAccess.end(), access) == limitAccess.end()) + continue; auto const tab = line.find('\t'); if (tab == std::string::npos) - info.list.emplace_back(std::move(line)); + { + if (prefixAccess.empty()) + info.list.emplace_back(std::move(line)); + else + info.list.emplace_back(prefixAccess + '+' + line); + } else { auto uri = line.substr(0, tab); + if (prefixAccess.empty() == false) + uri = prefixAccess + '+' + uri; auto tagline = line.substr(tab + 1); std::replace_if(tagline.begin(), tagline.end(), isspace_ascii, ' '); auto tags = VectorizeString(tagline, ' '); @@ -290,7 +321,20 @@ std::string MirrorMethod::GetMirrorFileURI(std::string const &Message, FetchItem continue; auto const plus = uristr.find("+"); if (plus < colon) - return uristr.substr(plus + 1); + { + // started as tor+mirror+http we want to get the file via tor+http + auto access = uristr.substr(0, colon); + std::string prefixAccess; + if (APT::String::Startswith(access, "mirror") == false) + { + prefixAccess = uristr.substr(0, plus); + access.erase(0, plus + 1); + uristr.erase(plus, strlen("mirror") + 1); + return uristr; + } + else + return uristr.substr(plus + 1); + } else { uristr.replace(0, strlen("mirror"), "http"); -- cgit v1.2.3