X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/b74d2d3af3238210bfafe57562d3670327918cd9..f7f0d6c7560a8f71707e7852a512469147aa9f84:/apt-pkg/indexcopy.cc diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index 0142d7dbe..b262e21c4 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include /*}}}*/ @@ -41,7 +43,7 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector &List, pkgCdromStatus *log) { OpProgress *Progress = NULL; - if (List.size() == 0) + if (List.empty() == true) return true; if(log) @@ -52,7 +54,7 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector &List, // Prepare the progress indicator unsigned long TotalSize = 0; - for (vector::iterator I = List.begin(); I != List.end(); I++) + for (vector::iterator I = List.begin(); I != List.end(); ++I) { struct stat Buf; if (stat(string(*I + GetFileName()).c_str(),&Buf) != 0 && @@ -66,14 +68,14 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector &List, unsigned int NotFound = 0; unsigned int WrongSize = 0; unsigned int Packages = 0; - for (vector::iterator I = List.begin(); I != List.end(); I++) + for (vector::iterator I = List.begin(); I != List.end(); ++I) { string OrigPath = string(*I,CDROM.length()); unsigned long FileSize = 0; // Open the package file FileFd Pkg; - if (FileExists(*I + GetFileName()) == true) + if (RealFileExists(*I + GetFileName()) == true) { Pkg.Open(*I + GetFileName(),FileFd::ReadOnly); FileSize = Pkg.Size(); @@ -130,9 +132,14 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector &List, (*I).c_str() + CDROM.length(),GetFileName()); string TargetF = _config->FindDir("Dir::State::lists") + "partial/"; TargetF += URItoFileName(S); + FileFd Target; if (_config->FindB("APT::CDROM::NoAct",false) == true) + { TargetF = "/dev/null"; - FileFd Target(TargetF,FileFd::WriteEmpty); + Target.Open(TargetF,FileFd::WriteExists); + } else { + Target.Open(TargetF,FileFd::WriteAtomic); + } FILE *TargetFl = fdopen(dup(Target.Fd()),"w"); if (_error->PendingError() == true) return false; @@ -275,7 +282,7 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector &List, _error->Warning("No valid records were found."); if (NotFound + WrongSize > 10) - _error->Warning("Alot of entries were discarded, something may be wrong.\n"); + _error->Warning("A lot of entries were discarded, something may be wrong.\n"); return true; @@ -525,21 +532,21 @@ bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex) // we skip non-existing files in the verifcation to support a cdrom // with no Packages file (just a Package.gz), see LP: #255545 // (non-existing files are not considered a error) - if(!FileExists(prefix+file)) + if(!RealFileExists(prefix+file)) { - _error->Warning("Skipping non-exisiting file %s", string(prefix+file).c_str()); + _error->Warning(_("Skipping nonexistent file %s"), string(prefix+file).c_str()); return true; } if (!Record) { - _error->Warning("Can't find authentication record for: %s",file.c_str()); + _error->Warning(_("Can't find authentication record for: %s"), file.c_str()); return false; } if (!Record->Hash.VerifyFile(prefix+file)) { - _error->Warning("Hash mismatch for: %s",file.c_str()); + _error->Warning(_("Hash mismatch for: %s"),file.c_str()); return false; } @@ -563,7 +570,7 @@ bool SigVerify::CopyMetaIndex(string CDROM, string CDName, /*{{{*/ FileFd Target; FileFd Rel; - Target.Open(TargetF,FileFd::WriteEmpty); + Target.Open(TargetF,FileFd::WriteAtomic); Rel.Open(prefix + file,FileFd::ReadOnly); if (_error->PendingError() == true) return false; @@ -576,13 +583,13 @@ bool SigVerify::CopyMetaIndex(string CDROM, string CDName, /*{{{*/ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector &SigList, /*{{{*/ vector PkgList,vector SrcList) { - if (SigList.size() == 0) + if (SigList.empty() == true) return true; bool Debug = _config->FindB("Debug::aptcdrom",false); // Read all Release files - for (vector::iterator I = SigList.begin(); I != SigList.end(); I++) + for (vector::iterator I = SigList.begin(); I != SigList.end(); ++I) { if(Debug) cout << "Signature verify for: " << *I << endl; @@ -590,66 +597,34 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector &SigList, indexRecords *MetaIndex = new indexRecords; string prefix = *I; + string const releasegpg = *I+"Release.gpg"; + string const release = *I+"Release"; + // a Release.gpg without a Release should never happen - if(!FileExists(*I+"Release")) + if(RealFileExists(release) == false) { delete MetaIndex; continue; } - - // verify the gpg signature of "Release" - // gpg --verify "*I+Release.gpg", "*I+Release" - const char *Args[400]; - unsigned int i = 0; - - string gpgvpath = _config->Find("Dir::Bin::gpg", "/usr/bin/gpgv"); - string pubringpath = _config->Find("Apt::GPGV::TrustedKeyring", "/etc/apt/trusted.gpg"); - string releasegpg = *I+"Release.gpg"; - string release = *I+"Release"; - - Args[i++] = gpgvpath.c_str(); - Args[i++] = "--keyring"; - Args[i++] = pubringpath.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[i++] = Opts->Value.c_str(); - if(i >= 390) { - _error->Error("Argument list from Acquire::gpgv::Options too long. Exiting."); - return false; - } - } - } - - Args[i++] = releasegpg.c_str(); - Args[i++] = release.c_str(); - Args[i++] = NULL; - pid_t pid = ExecFork(); if(pid < 0) { _error->Error("Fork failed"); return false; } - if(pid == 0) { - execvp(gpgvpath.c_str(), (char**)Args); - } + if(pid == 0) + RunGPGV(release, releasegpg); + if(!ExecWait(pid, "gpgv")) { _error->Warning("Signature verification failed for: %s", - string(*I+"Release.gpg").c_str()); + releasegpg.c_str()); // something went wrong, don't copy the Release.gpg // FIXME: delete any existing gpg file? continue; } // Open the Release file and add it to the MetaIndex - if(!MetaIndex->Load(*I+"Release")) + if(!MetaIndex->Load(release)) { _error->Error("%s",MetaIndex->ErrorText.c_str()); return false; @@ -658,7 +633,7 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector &SigList, // go over the Indexfiles and see if they verify // if so, remove them from our copy of the lists vector keys = MetaIndex->MetaKeys(); - for (vector::iterator I = keys.begin(); I != keys.end(); I++) + for (vector::iterator I = keys.begin(); I != keys.end(); ++I) { if(!Verify(prefix,*I, MetaIndex)) { // something went wrong, don't copy the Release.gpg @@ -676,6 +651,124 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector &SigList, CopyMetaIndex(CDROM, Name, prefix, "Release.gpg"); } + return true; +} + /*}}}*/ +// SigVerify::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. Also, as + the cdrom code currently can not use the gpgv method we have two places + these need to be done - so the place for this method is wrong but better + than code duplication… */ +bool SigVerify::RunGPGV(std::string const &File, std::string const &FileGPG, + int const &statusfd, int fd[2]) +{ + if (File == FileGPG) + { + #define SIGMSG "-----BEGIN PGP SIGNED MESSAGE-----\n" + char buffer[sizeof(SIGMSG)]; + FILE* gpg = fopen(File.c_str(), "r"); + if (gpg == NULL) + return _error->Errno("RunGPGV", _("Could not open file %s"), File.c_str()); + char const * const test = fgets(buffer, sizeof(buffer), gpg); + fclose(gpg); + if (test == NULL || strcmp(buffer, SIGMSG) != 0) + return _error->Error(_("File %s doesn't start with a clearsigned message"), File.c_str()); + #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 + return _error->Error(_("No keyring installed in %s."), + _config->FindDir("Dir::Etc::TrustedParts").c_str()); + } + + Args.push_back(gpgvpath.c_str()); + Args.push_back("--ignore-time-conflict"); + + if (statusfd != -1) + { + Args.push_back("--status-fd"); + char fd[10]; + snprintf(fd, sizeof(fd), "%i", statusfd); + Args.push_back(fd); + } + + 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 + dup2(nullfd, STDOUT_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]); return true; } /*}}}*/ @@ -683,7 +776,7 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ vector &List, pkgCdromStatus *log) { OpProgress *Progress = NULL; - if (List.size() == 0) + if (List.empty() == true) return true; if(log) @@ -693,7 +786,7 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ // Prepare the progress indicator unsigned long TotalSize = 0; - for (vector::iterator I = List.begin(); I != List.end(); I++) + for (vector::iterator I = List.begin(); I != List.end(); ++I) { struct stat Buf; if (stat(string(*I).c_str(),&Buf) != 0 && @@ -707,14 +800,14 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ unsigned int NotFound = 0; unsigned int WrongSize = 0; unsigned int Packages = 0; - for (vector::iterator I = List.begin(); I != List.end(); I++) + for (vector::iterator I = List.begin(); I != List.end(); ++I) { string OrigPath = string(*I,CDROM.length()); unsigned long FileSize = 0; // Open the package file FileFd Pkg; - if (FileExists(*I) == true) + if (RealFileExists(*I) == true) { Pkg.Open(*I,FileFd::ReadOnly); FileSize = Pkg.Size(); @@ -773,7 +866,7 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ TargetF += URItoFileName(S); if (_config->FindB("APT::CDROM::NoAct",false) == true) TargetF = "/dev/null"; - FileFd Target(TargetF,FileFd::WriteEmpty); + FileFd Target(TargetF,FileFd::WriteAtomic); FILE *TargetFl = fdopen(dup(Target.Fd()),"w"); if (_error->PendingError() == true) return false; @@ -847,7 +940,7 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ _error->Warning("No valid records were found."); if (NotFound + WrongSize > 10) - _error->Warning("Alot of entries were discarded, something may be wrong.\n"); + _error->Warning("A lot of entries were discarded, something may be wrong.\n"); return true;