diff options
Diffstat (limited to 'apt-pkg')
| -rw-r--r-- | apt-pkg/contrib/gpgv.cc | 100 | ||||
| -rw-r--r-- | apt-pkg/contrib/gpgv.h | 8 |
2 files changed, 65 insertions, 43 deletions
diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc index 611f4bfa7..43c634dde 100644 --- a/apt-pkg/contrib/gpgv.cc +++ b/apt-pkg/contrib/gpgv.cc @@ -18,11 +18,13 @@ #include <unistd.h> #include <algorithm> +#include <forward_list> #include <fstream> #include <iostream> #include <memory> #include <sstream> #include <string> +#include <unordered_map> #include <vector> #include <apti18n.h> @@ -138,6 +140,54 @@ static void APT_PRINTF(5) apt_msg(std::string const &tag, std::ostream &outterm, outterm << errtext << std::flush; } } + +static bool CheckGPGV(std::unordered_map<std::string, std::forward_list<std::string>> &checkedCommands, std::string gpgv, bool Debug) +{ + if (checkedCommands.find(gpgv) == checkedCommands.end()) + { + // Create entry + checkedCommands[gpgv]; + FileFd dumpOptions; + pid_t child; + const char *argv[] = {gpgv.c_str(), "--dump-options", nullptr}; + if (unlikely(Debug)) + std::clog << "Executing " << gpgv << " --dump-options" << std::endl; + if (not Popen(argv, dumpOptions, child, FileFd::ReadOnly) && Debug) + return false; + + for (std::string line; dumpOptions.ReadLine(line);) + { + if (unlikely(Debug)) + std::clog << "Read line: " << line << std::endl; + checkedCommands[gpgv].push_front(APT::String::Strip(line)); + } + dumpOptions.Close(); + waitpid(child, NULL, 0); + } + return not checkedCommands[gpgv].empty(); +} + +std::pair<std::string, std::forward_list<std::string>> APT::Internal::FindGPGV(bool Debug) +{ + static thread_local std::unordered_map<std::string, std::forward_list<std::string>> checkedCommands; + const std::string gpgvVariants[] = { + _config->Find("Apt::Key::gpgvcommand"), + // Prefer absolute path + "/usr/bin/gpgv-sq", + "/usr/bin/gpgv", + "/usr/bin/gpgv2", + "/usr/bin/gpgv1", + "gpgv-sq", + "gpgv", + "gpgv2", + "gpgv1", + }; + for (auto gpgv : gpgvVariants) + if (CheckGPGV(checkedCommands, gpgv, Debug)) + return std::make_pair(gpgv, checkedCommands[gpgv]); + return {}; +} + void ExecGPGV(std::string const &File, std::string const &FileGPG, int const &statusfd, int fd[2], std::string const &key) { @@ -148,13 +198,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG, void ExecGPGV(std::string const &File, std::string const &FileGPG, int const &statusfd, int fd[2], std::vector<std::string> const &KeyFiles) { - #define EINTERNAL 111 - const std::string gpgvVariants[] = { - "/usr/bin/gpgv-sq", - "/usr/bin/gpgv", - "/usr/bin/gpgv2", - "/usr/bin/gpgv", - }; +#define EINTERNAL 111 bool const Debug = _config->FindB("Debug::Acquire::gpgv", false); struct exiter { std::vector<std::string> files; @@ -165,24 +209,11 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG, } } local_exit; - std::string gpgv = _config->Find("Apt::Key::gpgvcommand"); - if (gpgv.empty() || !FileExists(gpgv)) + auto [gpgv, supportedOptions] = APT::Internal::FindGPGV(Debug); + if (gpgv.empty()) { - gpgv = ""; - for (auto gpgvVariant : gpgvVariants) - { - if (FileExists(gpgvVariant)) - { - gpgv = gpgvVariant; - break; - } - } - - if (gpgv.empty()) - { - apt_error(std::cerr, statusfd, fd, "Couldn't find a gpgv binary"); - local_exit(EINTERNAL); - } + apt_error(std::cerr, statusfd, fd, "Couldn't find a gpgv binary"); + local_exit(EINTERNAL); } std::vector<std::string> Args; @@ -303,25 +334,8 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG, if (auto assertPubkeyAlgo = _config->Find("Apt::Key::assert-pubkey-algo"); not assertPubkeyAlgo.empty()) { - FileFd dumpOptions; - pid_t child; - if (Debug) - std::clog << "Calling " << gpgv << " --dump-options" << std::endl; - const char* argv[] = {gpgv.c_str(), "--dump-options", nullptr}; - if (not Popen(argv, dumpOptions, child, FileFd::ReadOnly) && Debug) - std::clog << "Failed to call " << gpgv << " --dump-options" << std::endl; - for (std::string line; dumpOptions.ReadLine(line); ) - { - if (Debug) - std::clog << "Read line: " << line << std::endl; - if (APT::String::Strip(line) == "--assert-pubkey-algo") - { - Args.push_back("--assert-pubkey-algo=" + assertPubkeyAlgo); - break; - } - } - dumpOptions.Close(); - waitpid(child, NULL, 0); + if (std::find(supportedOptions.begin(), supportedOptions.end(), "--assert-pubkey-algo") != supportedOptions.end()) + Args.push_back("--assert-pubkey-algo=" + assertPubkeyAlgo); } Configuration::Item const *Opts; diff --git a/apt-pkg/contrib/gpgv.h b/apt-pkg/contrib/gpgv.h index 62c92f271..d4520f3a2 100644 --- a/apt-pkg/contrib/gpgv.h +++ b/apt-pkg/contrib/gpgv.h @@ -11,12 +11,20 @@ #include <apt-pkg/macros.h> +#include <forward_list> #include <string> #include <vector> class FileFd; +#ifdef APT_COMPILING_APT +namespace APT::Internal +{ +APT_PUBLIC std::pair<std::string, std::forward_list<std::string>> FindGPGV(bool Debug); +} +#endif + /** \brief generates and run the command to verify a file with gpgv * * If File and FileSig specify the same file it is assumed that we |
