// -*- mode: cpp; mode: fold -*- // Include Files /*{{{*/ #include #include #include #include #include #include #include #include #include #include #include #include /*}}}*/ using namespace std; // RunGPGV - returns the command needed for verify /*{{{*/ // --------------------------------------------------------------------- /* Generating the commandline for calling gpgv is somehow complicated as we need to add multiple keyrings and user supplied options. */ void ExecGPGV(std::string const &File, std::string const &FileGPG, int const &statusfd, int fd[2]) { #define EINTERNAL 111 if (File == FileGPG) { #define SIGMSG "-----BEGIN PGP SIGNED MESSAGE-----\n" char buffer[sizeof(SIGMSG)]; FILE* gpg = fopen(File.c_str(), "r"); if (gpg == NULL) { ioprintf(std::cerr, _("Could not open file %s"), File.c_str()); exit(EINTERNAL); } char const * const test = fgets(buffer, sizeof(buffer), gpg); fclose(gpg); if (test == NULL || strcmp(buffer, SIGMSG) != 0) { ioprintf(std::cerr, _("File %s doesn't start with a clearsigned message"), File.c_str()); exit(EINTERNAL); } #undef SIGMSG } string const gpgvpath = _config->Find("Dir::Bin::gpg", "/usr/bin/gpgv"); // FIXME: remove support for deprecated APT::GPGV setting string const trustedFile = _config->Find("APT::GPGV::TrustedKeyring", _config->FindFile("Dir::Etc::Trusted")); string const trustedPath = _config->FindDir("Dir::Etc::TrustedParts"); bool const Debug = _config->FindB("Debug::Acquire::gpgv", false); if (Debug == true) { std::clog << "gpgv path: " << gpgvpath << std::endl; std::clog << "Keyring file: " << trustedFile << std::endl; std::clog << "Keyring path: " << trustedPath << std::endl; } std::vector keyrings; if (DirectoryExists(trustedPath)) keyrings = GetListOfFilesInDir(trustedPath, "gpg", false, true); if (RealFileExists(trustedFile) == true) keyrings.push_back(trustedFile); std::vector Args; Args.reserve(30); if (keyrings.empty() == true) { // TRANSLATOR: %s is the trusted keyring parts directory ioprintf(std::cerr, _("No keyring installed in %s."), _config->FindDir("Dir::Etc::TrustedParts").c_str()); exit(EINTERNAL); } Args.push_back(gpgvpath.c_str()); Args.push_back("--ignore-time-conflict"); char statusfdstr[10]; if (statusfd != -1) { Args.push_back("--status-fd"); snprintf(statusfdstr, sizeof(fd), "%i", statusfd); Args.push_back(statusfdstr); } for (vector::const_iterator K = keyrings.begin(); K != keyrings.end(); ++K) { Args.push_back("--keyring"); Args.push_back(K->c_str()); } Configuration::Item const *Opts; Opts = _config->Tree("Acquire::gpgv::Options"); if (Opts != 0) { Opts = Opts->Child; for (; Opts != 0; Opts = Opts->Next) { if (Opts->Value.empty() == true) continue; Args.push_back(Opts->Value.c_str()); } } Args.push_back(FileGPG.c_str()); if (FileGPG != File) Args.push_back(File.c_str()); Args.push_back(NULL); if (Debug == true) { std::clog << "Preparing to exec: " << gpgvpath; for (std::vector::const_iterator a = Args.begin(); *a != NULL; ++a) std::clog << " " << *a; std::clog << std::endl; } if (statusfd != -1) { int const nullfd = open("/dev/null", O_RDONLY); close(fd[0]); // Redirect output to /dev/null; we read from the status fd if (statusfd != STDOUT_FILENO) dup2(nullfd, STDOUT_FILENO); if (statusfd != STDERR_FILENO) dup2(nullfd, STDERR_FILENO); // Redirect the pipe to the status fd (3) dup2(fd[1], statusfd); putenv((char *)"LANG="); putenv((char *)"LC_ALL="); putenv((char *)"LC_MESSAGES="); } execvp(gpgvpath.c_str(), (char **) &Args[0]); ioprintf(std::cerr, "Couldn't execute %s to check %s", Args[0], File.c_str()); exit(EINTERNAL); } /*}}}*/